2010-08-05 95 views
4

我想在Canvas上測試一堆用戶控件。我不希望HitTest()遍歷整個可視化樹,所以我使用FilterCallback來確保我只是命中測試UserControl。問題與WPF中的VisualTreeHelper.HitTest

我的問題是,用戶控件從來沒有打,它應該,但它沒有。如果我使用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,並向其提供將來自其預期的默認行爲:

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

(當然,你可以使事情變得複雜和命中測試實際的孩子或th他們的邊界框的組合,但對我來說,用戶控件的邊界框是足夠好的;另外,如果您想針對幾何體進行點擊測試,則需要覆蓋第二個超載。)

這使得它按預期工作,在篩選器中使用HitTestFilterBehavior.ContinueSkipChildren時篩選出子項。

+0

可以確認這個工作。應該是被接受的答案,因爲它比手動搜索視覺樹更好。 – Lennart 2016-07-05 12:48:37