命中测试行为

时间:2010-12-01 10:47:36

标签: .net wpf hittest

我有以下代码

public partial class MainWindow : Window
{
    public MainWindow() {
        InitializeComponent();
    }

    List<UIElement> ucs = new List<UIElement>();

    private void Window_PreviewMouseLeftButtonDown(object sender,
        MouseButtonEventArgs e)
    {
        ucs.Clear();

        Point p = e.GetPosition((UIElement)sender);

        VisualTreeHelper.HitTest(this, null,
            new HitTestResultCallback(MyHitTestCallback),
            new PointHitTestParameters(p));

        Console.WriteLine("ucs.Count = {0}", ucs.Count);

        foreach (var item in ucs)
        {
            Console.WriteLine("item: {0}", item.ToString());
        }
    }

    HitTestResultBehavior MyHitTestCallback(HitTestResult result)
    {
        ucs.Add(result.VisualHit as UIElement);
        return HitTestResultBehavior.Continue;
    }
}

这是我的窗口

<Window>
    <Grid>
        <my:UserControl1 HorizontalAlignment="Left" Margin="82,88,0,0" x:Name="userControl11" VerticalAlignment="Top" />
        <my:UserControl1 HorizontalAlignment="Left" Margin="168,166,0,0" x:Name="userControl12" VerticalAlignment="Top" />
        <my:UserControl1 HorizontalAlignment="Left" Margin="231,130,0,0" x:Name="userControl13" VerticalAlignment="Top" />
    </Grid>
</Window>

这是我的UC

<UserControl>
    <Grid>
        <Label Content="Label" Height="44" HorizontalAlignment="Left" Name="label1" VerticalAlignment="Top" FontSize="20" FontWeight="Bold" Width="78" Background="#FF4B9FC4" BorderBrush="#FF020A0D" BorderThickness="1" />
    </Grid>
</UserControl>

这是我单击ON A USER CONTROL时的输出,然后是2个UserControls的交叉点:

ucs.Count = 2
item: System.Windows.Controls.Border
item: System.Windows.Controls.Border
ucs.Count = 3
item: System.Windows.Controls.Border
item: System.Windows.Controls.Border
item: System.Windows.Controls.Border

为什么这样?鼠标实例下的UserControl在哪里?

PS:
现在,当我在标签上BorderThickness = 0

ucs.Count = 3
item: System.Windows.Controls.TextBlock
item: System.Windows.Controls.Border
item: System.Windows.Controls.Border
ucs.Count = 3
item: System.Windows.Controls.TextBlock
item: System.Windows.Controls.Border
item: System.Windows.Controls.Border

1 个答案:

答案 0 :(得分:2)

UserControl1是不可见的。它的内容是可见的,但您的UserControl1实例本身没有任何自己的视觉效果。 (它永远不会。用户控件的工作实际上只是包含其他东西。)

命中测试仅报告对可视树做出直接贡献的元素。而且由于命中测试会单独考虑每个元素,这意味着纯粹作为容器的元素不会显示出来。 (另一个相关的事实是,热门测试只考虑实际绘制的像素。所以如果你有一个Border,你设置BorderBrush和非零BorderThickness但是你没有Background,命中测试只会将边框轮廓视为一个命中 - 边框内的点将不会被视为撞击边框,因为它没有在其内部绘制任何东西。

如果你需要对“这个东西,或者这个东西里面的任何东西”进行打击测试,那么要么

  1. 使用鼠标进入/离开事件 - 那些气泡,因此即使在隐形容器元素上也会被提升
  2. 使用IsMouseOver
  3. 使用您正在使用的命中测试功能,将用户控件作为第一个参数传递,并将任何匹配视为命中测试点位于用户控件内的指示
  4. 第三个更复杂,但是如果你需要点击当前鼠标以外的测试点,你需要使用它。