zoukankan      html  css  js  c++  java
  • 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
    
    }
    View Code
  • 相关阅读:
    Hibernate save, saveOrUpdate, persist, merge, update 区别
    Eclipse下maven使用嵌入式(Embedded)Neo4j创建Hello World项目
    Neo4j批量插入(Batch Insertion)
    嵌入式(Embedded)Neo4j数据库访问方法
    Neo4j 查询已经创建的索引与约束
    Neo4j 两种索引Legacy Index与Schema Index区别
    spring data jpa hibernate jpa 三者之间的关系
    maven web project打包为war包,目录结构的变化
    创建一个maven web project
    Linux下部署solrCloud
  • 原文地址:https://www.cnblogs.com/CSSZBB/p/11588931.html
Copyright © 2011-2022 走看看