2010-08-05 4 views
4

Я пытаюсь испытать кучу UserControls на холсте. Я не хочу, чтобы HitTest() проходил весь путь через визуальное дерево, поэтому я использую FilterCallback, чтобы убедиться, что я только проверял UserControl.Проблема с VisualTreeHelper.HitTest в WPF

Моя проблема заключается в том, что UserControl никогда не ударяет, но это не так. Если я использую FilterCallback, я возвращаю, что он ничего не ударил. Если я разрешаю HitTest проходить через визуальное дерево, он пропускает UserControl.

Вот код:

<Canvas x:Name="Container"> 
<UserControl> 
    <Grid> 
     <Rectangle /> 
    </Grid> 
</UserControl> 
<UserControl> 
    <Grid> 
     <Rectangle /> 
    </Grid> 
</UserControl> 
</Canvas> 

... 
VisualTreeHelper.HitTest(Container, OnFilter, OnResult, myPoint); 
... 

private void OnResult(DependencyObject o) 
{ 
    //I'll get the Rectangle here, but never the userControl 
} 

private void OnFilter(DependencyObject o) 
{ 
    //I will get the UserControl here, but even when I do nothing more than continue, it will not trigger a visualHit. But the child rectangle will. 
} 

ответ

2

У меня была эта же проблема HitTest не найти пользовательский элемент управления. По-видимому, это по дизайну (http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/005dad03-c8eb-405f-9567-50653a0e612c).

Я работал над этим, обрабатывая попадание какого-либо элемента внутри пользовательского элемента управления, а затем находя родительский элемент управления пользователя с помощью метода VisualTreeHelper.GetParent. Я еще не очень хорошо знаком с WPF, поэтому я не уверен, что было бы лучше использовать свойство FrameworkElement.Parent.

Однако, вот мой метод для нахождения пользовательского элемента управления (или любого визуального родителя какого-либо требуемого типа) после первого обнаружения некоторых его элементов контента попадания теста:

public static T GetVisualParent<T>(this DependencyObject element) where T : DependencyObject 
{ 
    while (element != null && !(element is T)) 
     element = VisualTreeHelper.GetParent(element); 

    return (T)element; 
} 
11

Я знаю, что это довольно чертовски поздно чтобы ответить на этот вопрос, но здесь идет: другой подход переопределить HitTestCore на UserControl и обеспечить его поведение по умолчанию, которое можно было бы ожидать от него:

protected override System.Windows.Media.HitTestResult HitTestCore(System.Windows.Media.PointHitTestParameters hitTestParameters) 
{ 
    return new PointHitTestResult(this, hitTestParameters.HitPoint); 
} 

(конечно, вы могли бы осложнить вещи и хит-теста фактические дети или комбинация n их ограничивающих прямоугольников, но для меня ограничивающая рамка пользовательского контроля была достаточно хороша; также, если вы хотите провести тест против геометрии, вам также необходимо переопределить эту вторую перегрузку.)

Это заставляет его работать должным образом, отфильтровывая детей при использовании HitTestFilterBehavior.ContinueSkipChildren в фильтре.

+0

Может подтвердить, что это работает. Должен быть принятый ответ, поскольку он лучше, чем поиск по визуальному дереву вручную. – Lennart

Смежные вопросы