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"> ...
随机推荐
- 传统.NET 4.x应用容器化体验(2)
上一篇我们基于Windwos Server 2019 with Container初步跑了一个ASP.NET WebForm应用程序.本篇我们来自己编译部署一个ASP.NET MVC应用程序到Wind ...
- Java基础00-网络编程29
1. 网络编程入门 1.1 网络编程概述 1.2 网络编程三要素 1.3 IP地址 在命令提示符中使用 1.4 InetAddress的使用 代码示例: public class InetAddres ...
- [刘阳Java]_Web前端入门级练习_迅雷官宣网设计
也有一段时间没有写一些技术专题文章,今天给大家来几篇Web前端入门级练习的文章.主讲<迅雷官宣网>的设计,相信大家平时也用过迅雷这个下载工具,所以分享的这篇技术大家在一定程序会感兴趣. 先 ...
- 【论文阅读】DSDNet Deep Structured self-Driving Network
前言引用 [2] DSDNet Deep Structured self-Driving Network Wenyuan Zeng, Shenlong Wang, Renjie Liao, Yun C ...
- POJ 博弈论
poj1704 Georgia and Bob 题目链接:http://poj.org/problem?id=1704 题意:如图所示,两个人在玩一个游戏,排成直线的格子上有n个棋子,两人依次将棋子向 ...
- mpvue开发小程序项目遇到的问题
mpvue项目 最近用mpvue开发了一个家庭私人医生签约的小程序项目.记录总结一下,开发过程中遇到的一些问题. 关于页面进栈出栈的状态值问题 页面进出栈,会触发onLoad/unLoad事件.出栈不 ...
- PAT乙级:1063 计算谱半径 (20分)
PAT乙级:1063 计算谱半径 (20分) 题干 在数学中,矩阵的"谱半径"是指其特征值的模集合的上确界.换言之,对于给定的 n 个复数空间的特征值 { a1+b1i,⋯,a** ...
- C++第四十二篇 -- CPU Usage
前言 目的:读取并控制CPU占用率 近期在做CPU Usage方面的事情,让CPU以一种高占用率的状态运行一定的时间,需要读取CPU各个核的占用率,网上关于这方面的资料好少,FQ也只找到了一个WMI的 ...
- vue点击复制功能
复制功能,选中复制或者点击复制(不使用插件的情况下) 1.选中复制 这个比点击复制简单点 <template> <div> <el-button type=& ...
- 【网站公告】避免反对百度的限制措施:百度搜索过来的访问会自动禁用js权限
今天下午百度联系我们,发现通过百度搜索访问我们网站的博文时会出现下面反对百度的画面,让我们今天彻底处理好,保证不再出现这种情况. 我们排查后发现是这位博主申请了js权限,添加了下面的反对百度的脚本: ...