2012-04-27 2 views
0

Мне нужно найти UIElement s in (rectangle/area/bounds).Как я могу найти UIElements в прямоугольнике в WPF?

MainWindow Я делаю следующее:

  • зарегистрировать мышь вниз, в исходное положение.
  • Я регистрирую положение мыши вверх.
  • Теперь мне нужно найти ll (кнопки, текстовые поля и т. Д.) В прямоугольнике между началом положение и конечное положение.

Я нашел в методе msdn HitTest, но это только для одной точки. Я думаю, что, пройдя все точки в созданном прямоугольнике , это катастрофа производительности.

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

Мой код основан на MVVM схеме:

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, чтобы использовать ActualWidth и ActualHeight свойства

Затем создать статический класс, который делает некоторые математические 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

Это звучит очень хорошо, я попробую сейчас поблагодарить. –

+0

Привет, астральный, спасибо за ответ, он работает, но проблема в том, что этот подход повреждает шаблон MVVM: ObservableCollection Ячейки в представленииModel - это проблема FrameWorkElement - это представление. –

+0

Вы правы. Но вы должны посмотреть здесь: [ссылка] (http://stackoverflow.com/questions/1083224/pushing-read-only-gui-properties-back-into-viewmodel) И может быть создано FramworkElementViewModel – astreal

0

Astreal еще раз спасибо за ваш ответ. Готово. Я просто переместил код выбора из modelView для просмотра. Выбор выполняется только в пользовательском интерфейсе.

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); 
     } 
     } 
    }