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
  • 相关阅读:
    volatile详解
    Java并发之AQS详解
    Thread详解
    Hibernate检索策略
    Hibernate查询方式
    Hibernate--对象关系
    hibernate--hibernate.cfg.xml常用配置详解
    hibernate--CRUD初体验
    hibernate--HelloWorld
    Struts支持的contentType
  • 原文地址:https://www.cnblogs.com/CSSZBB/p/11588931.html
Copyright © 2011-2022 走看看