有时候会有框选的需求,类似EXCEL一样,画一个框选择里面的子控件。

选择后比如可以将子控件的Border设置为红色边框

说下这个功能的大致原理。背景是一个Grid,比如里面放了很多的Button.  同时还有一个红色边框的RectAngele来显示框框。

RectAngele默认不显示。

鼠标左键按下时,记录当时鼠标位置作为RectAngele的左上角起点,

鼠标按住移动时,记录当时的鼠标位置作为RectAngele的右下角终点。

这样两点,就确定了RectAngele的位置,鼠标按住不停移动,这个RectAngele就会不停的变化大小。

用到了几个事件

PreviewMouseMove,PreviewMouseLeftButtonDown,PreviewMouseLeftButtonUp。

这样的功能,当然可以在业务层做 定义Grid Button RectRange 的界面XAML中做.。如果有多个界面要做框选功能,岂不是代码要复制来复制去复制几遍?

!这样太LOW,不能忍,必须抽象到控件层次,与业务逻辑无关。

新增控件 GridRect 继承 Grid,把框选功能集成到控件里。 这里有一个关键的地方,Grid有可能被分为很多Row 和Clomn。不同的Button放在不同的行列里。

但是这个RectRange 的位置其实是和行列无关的。它不能固定在某个行列里。所以RectRange要特殊处理。

废话不多说,直接上源码,拿去用吧!

public class GridRect : Grid
{
private Rectangle rect;
private Grid rectgrid;//因为可能被分为很多列和行,而rect的父容器不能被分组
public GridRect()
{ Background = Brushes.Transparent;
this.Loaded += GridRect_Loaded; } public delegate void delegateSelectChildChange(List<FrameworkElement> SelectedControls); public delegateSelectChildChange SelectChildChange { get; set; } private void GridRect_Loaded(object sender, RoutedEventArgs e)
{
rectgrid = new Grid();
rect = new Rectangle()
{
IsHitTestVisible = false,
StrokeThickness = 1,
Fill = Brushes.Transparent,
Visibility = System.Windows.Visibility.Collapsed,
Stroke = Brushes.Red,
HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
VerticalAlignment = System.Windows.VerticalAlignment.Top
}; //因为可能被分为很多列和行,而rect的父容器不能被分组
Grid.SetRowSpan(rectgrid, 100);
Grid.SetColumnSpan(rectgrid, 100); rectgrid.Children.Add(rect);
this.Children.Add(rectgrid); Panel.SetZIndex(rectgrid, 999);
} #region 框选功能 protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
var StartPoint = e.GetPosition(this);
RectStartPoint.X = Math.Truncate(StartPoint.X);
RectStartPoint.Y = Math.Truncate(StartPoint.Y); } protected override void OnPreviewKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.Key == Key.Escape && rect.Visibility == Visibility.Visible)
{
rect.Visibility = Visibility.Collapsed;
} } private Point RectStartPoint = new Point();
private Point RectEndPoint = new Point(); protected override void OnPreviewMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.LeftButton == MouseButtonState.Pressed)
{
//该事件在界面加载完后会马上出发,因为鼠标相对于grid的位置会更新,且Pressed,此时红框不该显示
if (rect.Visibility != Visibility.Visible
&& RectStartPoint.X + RectStartPoint.Y !=0)
{
rect.Visibility = Visibility.Visible;
} Point p = e.GetPosition(this); double width = Math.Truncate(Math.Abs(p.X - RectStartPoint.X));
double height = Math.Truncate(Math.Abs(p.Y - RectStartPoint.Y)); rect.Margin = new Thickness(RectStartPoint.X, RectStartPoint.Y, 0, 0); rect.Height = height;
rect.Width = width; RectEndPoint.X = RectStartPoint.X + width;
RectEndPoint.Y = RectStartPoint.Y + height; }
} protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
if (rect.Visibility == Visibility.Visible)
{
List<FrameworkElement> SelectedControlsTmp=new List<FrameworkElement>();
foreach (FrameworkElement item in this.Children)
{
if (item == rect || item ==rectgrid)
{
continue;
} GeneralTransform generalTransform1 = item.TransformToVisual(this); Point lefttop = generalTransform1.Transform(new Point(0, 0));
Point rightbuttom = new Point(lefttop.X + item.ActualWidth, lefttop.Y + item.ActualHeight); Point btnrighttop = new Point(rightbuttom.X, lefttop.Y);
Point btnleftbuttom = new Point(lefttop.X, rightbuttom.Y); Rect rectTmp = new Rect(lefttop, rightbuttom); Rect rectRed = new Rect(RectStartPoint, RectEndPoint); if (rectTmp.IntersectsWith(rectRed))
{
SelectedControlsTmp.Add(item);
}
}
SelectChildChange?.Invoke(SelectedControlsTmp);
}
} #endregion }

WPF Grid新增框选功能的更多相关文章

  1. Extjs grid分页多选记忆功能

    很多同事在用extjs grid做分页的时候,往往会想用grid的多选功能来实现导出Excel之类的功能(也就是所谓的多选记忆功能),但在选选择下一页的时候 上一页选中的已经清除 这是因为做分页的时候 ...

  2. Visual Studio的框选代码区块功能

    要从Visual Studio里复制代码粘贴到其他地方,会因为对齐的问题,造成粘贴的时候,代码左边带有大量的空格. 而VS有一个很好的功能就是框选功能,使用方法是,将光标放置在要框选代码的最左边,然后 ...

  3. CheckedListBoxControl 实现复选框的单选与多选功能

    由于工作需要,需要实现复选框的单选与多选功能,找了好多资料都不是很全,经过两天苦苦的挖挖挖,终于完成啦O(∩_∩)O哈哈~ 用DEV控件中的CheckedListBoxControl控件,当然VS中的 ...

  4. 使用JQuery做一组复选框的功能。

    之前做过复选框的功能,奈何笔记丢失,害的我又鼓捣了一番...还是博客园做笔记比较好. 假设现在有一个表格,每一行都有一个复选框按钮.在表头还有一个全选的复选框按钮. ①.当点击一个全选按钮时,下面的同 ...

  5. 原生js实现在表格用鼠标框选并有反选功能

    今天应同学要求,需要写一个像Excel那样框选高亮,并且实现框选区域实现反选功能.要我用原生js写,由于没什么经验翻阅了很多资料,第一次写文章希望各位指出不足!! 上来先建表 <div clas ...

  6. EasyUI datagrid 复选框可以多选但不能全选功能实现

    1.功能需求:  实现多选,但是不能够全选功能 2.js代码 //帮卖列表页面,可以多选但是不能够全选实现 $(".datagrid-header-check").children ...

  7. JavaScript学习笔记-商品管理新增/删除/修改功能

    <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...

  8. react 使用antd的多选功能做一个单选与全选效果

    一个小而简单的单选全选功能,其实官网已经给出效果了,不过是我多做了些复合用法 addorupdatemodal.jsx import React from "react"; imp ...

  9. Javascript-商品管理新增/删除/修改功能

    <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...

随机推荐

  1. 深入学习Netty(4)——Netty编程入门

    前言 从学习过BIO.NIO.AIO编程之后,就能很清楚Netty编程的优势,为什么选择Netty,而不是传统的NIO编程.本片博文是Netty的一个入门级别的教程,同时结合时序图与源码分析,以便对N ...

  2. C语言:\t\b\n应用

    #include <stdio.h> int main() { printf("123\n"); printf("%c\n",'\177'); pr ...

  3. ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放

    ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放 前言 加锁逻辑已经介绍完毕,那当一个线程重复加锁是如何处理的呢? 锁重入 在上一小节中,可以看到加锁的过程,再回头看 ...

  4. flutter实战demo,仿luckin coffee。

    flutter_luckin_coffee flutter luckin coffee application(仿瑞幸咖啡) 目录 前言 安卓扫码体验 flutter版本信息 安装 相关插件 维护者 ...

  5. if函数+isna函数+vlookup函数实现不同列相同单元格内容排列在同一行

    1,首先学习的网址:https://jingyan.baidu.com/album/22a299b5dd0f959e19376a22.html?picindex=1 2,excel 这也许是史上最好最 ...

  6. mpvue开发小程序项目遇到的问题

    mpvue项目 最近用mpvue开发了一个家庭私人医生签约的小程序项目.记录总结一下,开发过程中遇到的一些问题. 关于页面进栈出栈的状态值问题 页面进出栈,会触发onLoad/unLoad事件.出栈不 ...

  7. RHEL7配置端口转发和地址伪装

    说明:这里是Linux服务综合搭建文章的一部分,本文可以作为Linux上使用firewalld做端口转发和地址伪装以及外网访问内网的参考. 注意:这里所有的标题都是根据主要的文章(Linux基础服务搭 ...

  8. tomcat与springmvc 结合 之---第18篇 StandContext容器和SpringMVC的监听器的模型

    writedby张艳涛 如何使用tomcat的监听器 public class BootStrap_ex06 { public static void main(String[] args) { Ht ...

  9. c++ 的父类 new 重载, 子类new 对象的时候会调用父类的operater new

    子类在new 对象的 时候  父类的new 进行了重载,那么会调用父类的operater new() 函数 #include <iostream> #include <string& ...

  10. SpringCloud升级之路2020.0.x版-4.maven依赖回顾以及项目框架结构

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们先来回顾下 m ...