有时候会有框选的需求,类似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. LeetCode解题记录(双指针专题)

    1. 算法解释 双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务.也可以延伸到多个数组的多个指针. 若两个指针指向同一数组,遍历方向相同且不会相交,则也称为滑动窗口(两个指针包围的区域 ...

  2. [刘阳Java]_ResourceBundleViewResolver视图解析器_第7讲

    ResourceBundleViewResolver是根据proterties文件来找对应的视图来解析"逻辑视图".该properties文件默认是放在classpath路径下的v ...

  3. python + pytest基本使用方法(拓展库)

    一.测试钩子配置文件 import pytest# conftest.py 是pytest特有的本地测试配置文件;# 既可以用来设置项目级别的Fixture,也可用来导入外部插件,还可以指定钩子函数# ...

  4. odoo里面条件写法

    attrs="{'invisible': ['|', ('probability', '>', 0), ('active', '=', True)]}"/>. 写法gt ...

  5. 什么是ETL--ETL定义、过程和工具选型思路

    ETL代表"提取.转换和加载".ETL 过程在数据集成策略中起着关键作用.ETL允许企业从多个来源收集数据并将其整合到一个集中的位置.ETL还使不同类型的数据可以协同工作. 概述 ...

  6. 静态Web服务器(py版)

    近来,对http协议进行了研究,闲来无事.自己使用python3写了个静态Web服务器,以下是代码: static_Web_sever.py ''' 思路:首先使用socket创建tcp服务器,照旧绑 ...

  7. HSDB工具类使用探索jvm

    本文是引用https://club.perfma.com/article/2261053 有人问了个小问题,说: public class Test { static Test2 t1 = new T ...

  8. JSP的执行原理、JSP的内置对象、四大作用域解析、MVC模式理解>从零开始学JAVA系列

    目录 JSP的执行原理.JSP的内置对象.四大作用域解析.MVC模式理解 JSP的执行原理 这里拿一个小例子来解析JSP是如何被访问到的 首先将该项目部署到tomcat,并且通过tomcat启动 通过 ...

  9. DOS命令--Windows操作系统之母

    DOS命令 DOS是什么 解释:Disk Operating System的缩写,意思是"磁盘操作系统" 系统:DOS就是人给机器下达命令的集合,是存储在操作系统中的命令集 基本用 ...

  10. 获取元素在页面中位置 getBoundingClientRect()

    DOM 原生方法getBoundingClientRect()获取元素相对视口位置 DOMRect 对象包含了一组用于描述边框的只读属性--left.top.right和bottom,单位为像素.除了 ...