2012-04-27 34 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); 
     } 
     } 
    }