WPF Grid新增框选功能
有时候会有框选的需求,类似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新增框选功能的更多相关文章
- Extjs grid分页多选记忆功能
很多同事在用extjs grid做分页的时候,往往会想用grid的多选功能来实现导出Excel之类的功能(也就是所谓的多选记忆功能),但在选选择下一页的时候 上一页选中的已经清除 这是因为做分页的时候 ...
- Visual Studio的框选代码区块功能
要从Visual Studio里复制代码粘贴到其他地方,会因为对齐的问题,造成粘贴的时候,代码左边带有大量的空格. 而VS有一个很好的功能就是框选功能,使用方法是,将光标放置在要框选代码的最左边,然后 ...
- CheckedListBoxControl 实现复选框的单选与多选功能
由于工作需要,需要实现复选框的单选与多选功能,找了好多资料都不是很全,经过两天苦苦的挖挖挖,终于完成啦O(∩_∩)O哈哈~ 用DEV控件中的CheckedListBoxControl控件,当然VS中的 ...
- 使用JQuery做一组复选框的功能。
之前做过复选框的功能,奈何笔记丢失,害的我又鼓捣了一番...还是博客园做笔记比较好. 假设现在有一个表格,每一行都有一个复选框按钮.在表头还有一个全选的复选框按钮. ①.当点击一个全选按钮时,下面的同 ...
- 原生js实现在表格用鼠标框选并有反选功能
今天应同学要求,需要写一个像Excel那样框选高亮,并且实现框选区域实现反选功能.要我用原生js写,由于没什么经验翻阅了很多资料,第一次写文章希望各位指出不足!! 上来先建表 <div clas ...
- EasyUI datagrid 复选框可以多选但不能全选功能实现
1.功能需求: 实现多选,但是不能够全选功能 2.js代码 //帮卖列表页面,可以多选但是不能够全选实现 $(".datagrid-header-check").children ...
- JavaScript学习笔记-商品管理新增/删除/修改功能
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- react 使用antd的多选功能做一个单选与全选效果
一个小而简单的单选全选功能,其实官网已经给出效果了,不过是我多做了些复合用法 addorupdatemodal.jsx import React from "react"; imp ...
- Javascript-商品管理新增/删除/修改功能
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
随机推荐
- DHCP原理于配置
DHCP原理于配置 一.DHCP服务 1)使用DHCP的好处 2)DH ...
- Twain Capabilities
Paper Handling 纸操作 CAP_AUTOFEED MSG_SET为TRUE,启用Twain源的自动进纸. CAP_CLEARPAGE MSG_SET为TRUE,退出当前页面并清空数据. ...
- 高校表白App-团队冲刺第四天
今天要做什么 就如昨天所说,今天继续进行引导页制作的学习.并开始通过ViewPager做简单的布局与Activity. 遇到的问题 本来以为只是使用一个ViewPager控件就可以搞定,原来还是需要配 ...
- 【记录】如何造一个vite插件(2)
上一篇已经把vite插件的基础结构搭建起来了,这一次就来聊聊继续完善开发环境. 完善开发环境 生成d.ts文件 先来修改一下lib/index.ts这个文件 export interface user ...
- PAT甲级:1124 Raffle for Weibo Followers (20分)
PAT甲级:1124 Raffle for Weibo Followers (20分) 题干 John got a full mark on PAT. He was so happy that he ...
- PAT甲级:1089 Insert or Merge (25分)
PAT甲级:1089 Insert or Merge (25分) 题干 According to Wikipedia: Insertion sort iterates, consuming one i ...
- PAT乙级:1053 住房空置率 (20分)
PAT乙级:1053 住房空置率 (20分) 题干 在不打扰居民的前提下,统计住房空置率的一种方法是根据每户用电量的连续变化规律进行判断.判断方法如下: 在观察期内,若存在超过一半的日子用电量低于某给 ...
- 每天五分钟Go - 常量
常量的声明 常量使用const进行对不会被改变值的修饰符 const 常量名 [常量类型] = 常量值,和变量的声名一样可以省略类型 const a=1 const b="a" c ...
- 第一篇 -- Go环境的搭建以及Hello World程序编写
VS Code的下载和安装 1. 下载链接(本人下载版本VSCodeUserSetup-x64-1.57.0.exe) https://code.visualstudio.com/download 友 ...
- php-socket通信演示
client: error_reporting(E_ALL); set_time_limit(0); echo "<h2>TCP/IP Connection</h2> ...