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"> ...
随机推荐
- Ubuntu虚拟机基本环境搭建以及参数设置
# 设置root账户密码 sudo passwd root # 修改源镜像(提高下载更新速度) sudo apt-get update pip install open-vm-tools pip in ...
- Pandas高级教程之:稀疏数据结构
目录 简介 Spare data的例子 SparseArray SparseDtype Sparse的属性 Sparse的计算 SparseSeries 和 SparseDataFrame 简介 如果 ...
- 13、java——常用类
枚举类型 描述一种事物的所有情况|所有可能|所有实例 (1)通过enum关键字定义枚举类型 (2)枚举的成员,字段都作为当前枚举类型的实例存在,默认被public static final修 ...
- Redis学习——数据结构上
一.常用的全局命令 1.查看所有的键: KEYS * KEYS pattern:查找所有符合给定模式 pattern 的 key . KEYS 的速度非常快,但在一个大的数据库中使用它仍然可能造成性能 ...
- PAT乙级:1088 三人行 (20分)
PAT乙级:1088 三人行 (20分) 题干 子曰:"三人行,必有我师焉.择其善者而从之,其不善者而改之." 本题给定甲.乙.丙三个人的能力值关系为:甲的能力值确定是 2 位正整 ...
- npm 报错 : npm ERR! Maximum call stack size exceeded
解决方法:https://blog.csdn.net/caijunfen/article/details/81009797
- Gitlab-500错误的恢复
一.问题截图 二.定位问题 2.1.查看状态 # 查看状态 gitlab-ctl status # 如图发现gitaly 是down的状态 2.2.查看日志 # 查看日志 gitlab-ctl tai ...
- 第五篇 -- git基础教程
git(权威指南)基础教程第一章 git -- gitbash -- cygwin git service:gitolite 两个的目录不同 gitbash ~ windows/home/admini ...
- 误改win10下的windowsapps文件夹权限,导致自带应用闪退问题
在项目中,为了获得相关应用的具体位置(office的具体exe位置),修改了文件夹WindowsApps权限,导致所有自带应用打开闪退. 通过搜索相关资料,获得解决方法: 重置该文件的权限设置 ica ...
- etcd学习(5)-etcd的Raft一致性算法原理
ETCD的Raft一致性算法原理 前言 Raft原理了解 raft选举 raft中的几种状态 任期 leader选举 日志复制 安全性 leader宕机,新的leader未同步前任committed的 ...