2012-04-27 5 views
0

UIElement(矩形/領域/境界)を検索する必要があります。私は次のことをやっているWPFの矩形でUIElementsを検索するにはどうすればよいですか?

メインウィンドウ:

  • は私がダウン開始位置としてマウスを登録します。
  • 私はマウスを上に置きます。
  • ここでは、開始位置 と終了位置の間の矩形内にll(ボタン、テキストボックスなど)を見つける必要があります。

msdnで見つかったのはHitTestですが、これは1つのポイントのみです。私は、設立された 四角形のすべてのポイントを歩いていると、パフォーマンスの災害だと思います。 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

私はActualWidthActualHeightプロパティ

を使用するために、そして、それらにいくつかの数学MouseUtils

を行い、静的クラスを作成し、代わりにUIElementの(UIElementを拡張)FrameworkElementを使用します静的フィールド

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

これはとてもうれしいです。 –

+0

こんにちはastreal、答えていただきありがとうございますが、このアプローチはMVVMパターンを傷つけます:ObservableCollection viewModelのwellsはFrameWorkElementがViewです。 –

+0

あなたは正しいです。 しかし、ここで見てください: [リンク](http://stackoverflow.com/questions/1083224/pushing-read-only-gui-properties-back-into-viewmodel) そして、FramworkElementViewModelを作成することがあります – astreal

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); 
     } 
     } 
    } 
関連する問題