2012-04-27 36 views
0

我需要在(矩形/面积/边界)中找到UIElement s。如何在WPF矩形中找到UIElements?

主窗口我做了以下内容:

  • 我注册鼠标按下作为起始位置。
  • 我regsiter鼠标向上的位置。
  • 现在我需要在开始 位置和结束位置之间的矩形中找到ll(按钮,文本框等)。

我在msdn中发现HitTest的方法,但它只是一个点。我认为,在创建的 矩形中遍历所有点都是性能灾难。基于MVVM模式

http://msdn.microsoft.com/en-us/library/ms752097.aspx

我的代码:

private ObservableCollection<UIElementViewModel> wells; 
private Point stratPoint; // Mouse down 
public ICommand MouseUpRightCommand 
{ 
    get 
    { 
    if (this.mouseUpRightCommand == null) 
    { 
     this.mouseUpRightCommand = new RelayCommands(
     param => 
     { 
      if (param is MouseButtonEventArgs) 
      { 
      var e = (param as MouseButtonEventArgs); 

      //Set the end point 
      endPosition = e.GetPosition(((ItemsControl)e.Source)); 

      // for example, here I want to find all controls(UIElements) in the 
      // founded rectangle of stratPoint and endPosition. 

      } 
     }); 
    } 

    return this.mouseUpRightCommand; 
    } 
} 

任何其他想法或一个更好的方法?

感谢

回答

3

我会用FrameworkElement(延伸UIElement),而不是UIElement,为了使用ActualWidthActualHeight性能

然后创建一个静态类,做一些数学MouseUtils

与静态字段

private static double _dContainerTop; 
    private static double _dContainerBottom; 
    private static double _dContainerLeft; 
    private static double _dContainerRight; 
    private static double _dCursorTop; 
    private static double _dCursorLeft; 
    private static double _dCursorRight; 
    private static double _dCursorBottom; 

种那些静态方法

private static void FindValues(FrameworkElement element, Visual rootVisual) 
    { 
     var containerTopLeft = container.TransformToAncestor(rootVisual).Transform(new Point(0, 0)); 

     _dContainerTop = containerTopLeft.Y; 
     _dContainerBottom = _dContainerTop + container.ActualHeight; 
     _dContainerLeft = containerTopLeft.X; 
     _dContainerRight = _dContainerLeft + container.ActualWidth; 

    } 

public static bool IsElementUnderRectCursor(FrameworkElement element, Point startPoint, Point endPoint, Visual rootVisual) 
    { 
     _dCursorTop=Math.Min(startPoint.Y, endPoint.Y); 
     _dCursorBottom=Math.Max(startPoint.Y, endPoint.Y); 
     _dCursorLeft=Math.Min(startPoint.X, endPoint.X); 
     _dCursorRight=Math.Max(startPoint.X, endPoint.X); 

     FindValues(container, rootVisual); 
     if (_dContainerTop < _dCursorTop|| _dCursorBottom< _dContainerBottom) 
     { 
      return false; 
     } 
     if (_dContainerLeft < _dCursorLeft|| _dContainerRight < _dCursorRight) 
     { 
      return false; 
     } 
     return true; 
    } 

Rootvisual是你的,例如窗口;

然后通过ObservableCollection<FrameworkElement> wells循环并调用该函数IsElementUnderRectCursor。再次 Kinecting the Dots

+0

这听起来很不错,我现在试试看,谢谢。 – 2012-04-27 15:28:39

+0

嗨,真的,谢谢你的回答,它的工作,但问题这种方法伤害MVVM模式:ObservableCollection 井中viewModel是问题FrameWorkElement是一个视图。 – 2012-04-27 16:03:58

+0

你说得对。 但你应该看看这里: [link](http://stackoverflow.com/questions/1083224/pushing-read-only-gui-properties-back-into-viewmodel) 而且可能会创建一个FramworkElementViewModel – astreal 2012-04-27 16:46:54

0

Astreal谢谢您的回答:

这是从启发。完成。我只是从modelView中移动选择代码来查看。该选择仅在UI中完成。

private void SelectWells(RectangleGeometry selectionRectangle, FrameworkElement frameworkElement) 
    { 
     var items = GetItemsControl(frameworkElement); 

     foreach (var item in items.Items) 
     { 
     var viusalItem = (ContentPresenter)items.ItemContainerGenerator.ContainerFromItem(item); 

     var wellControl = this.GetWellControl(viusalItem); 

     var relativePoint = wellControl.TransformToAncestor(items).Transform(new Point(0, 0)); 

     var controlRectangle = 
      new RectangleGeometry(
      new Rect(relativePoint.X, relativePoint.Y, wellControl.ActualWidth, wellControl.ActualHeight)); 

     var intersectionGeometry = Geometry.Combine(
      selectionRectangle, controlRectangle, GeometryCombineMode.Intersect, null); 

     if (intersectionGeometry.GetArea() > 0) 
     { 
      wellControl.Command.Execute(this); 
     } 
     } 
    }