Wpf 命中测试添加到画布的子控件无效

Wpf 命中测试添加到画布的子控件无效,wpf,silverlight-4.0,sprite,Wpf,Silverlight 4.0,Sprite,我试图在运行时对添加到画布中的用户控件集合进行命中测试 我的画布: <Canvas x:Name="LayoutRoot" Background="White"> <Canvas x:Name="Carrier" Canvas.ZIndex="-1"> </Canvas> </Canvas> 我的画布代码: public MainPage() { InitializeComponent();

我试图在运行时对添加到画布中的用户控件集合进行命中测试

我的画布:

<Canvas x:Name="LayoutRoot" Background="White">
    <Canvas  x:Name="Carrier" Canvas.ZIndex="-1">
    </Canvas>
</Canvas>

我的画布代码:

    public MainPage()
    {
        InitializeComponent();

        var uiElement = new MyUserControl();
        this.Carrier.Children.Add(uiElement);

        MouseLeftButtonDown += MouseLeftButtonDownHandler;
    }

    private List<UIElement> HitSprite(Point p)
    {
        var hitElements = 
           VisualTreeHelper.FindElementsInHostCoordinates(p, this.Carrier) as List<UIElement>;

        return hitElements.Count > 0 ? hitElements : null;
    }

    private void MouseLeftButtonDownHandler(object sender, MouseButtonEventArgs e)
    {
        var list = HitSprite(e.GetPosition(this.LayoutRoot));
    }
public主页()
{
初始化组件();
var uiElement=new MyUserControl();
this.Carrier.Children.Add(uiElement);
MouseLeftButtonDown+=MouseLeftButtonDownHandler;
}
私有列表HitSprite(点p)
{
变量元素=
visualtreeheloper.FindElementsInHostCoordinates(p,this.Carrier)作为列表;
返回hitElements。计数>0?hitElements:null;
}
私有void MouseLeftButtonDownHandler(对象发送器,MouseButtonEventArgs e)
{
var list=HitSprite(e.GetPosition(this.LayoutRoot));
}
我的用户控件:

<Canvas x:Name="Container" AllowDrop="True">
    <StackPanel Name="Description" Height="65" Canvas.ZIndex="2" IsHitTestVisible="False">
        <TextBlock Text="Testing" x:Name="Name" FontSize="12" FontWeight="Bold" HorizontalAlignment="Center" IsHitTestVisible="False"/>

        <Border Background="Green">
            <Image x:Name="Body" Stretch="None" Canvas.ZIndex="0" Height="20" Width="20">
            </Image>
        </Border>
    </StackPanel>
</Canvas>

对于GetPoint和FindElementsInHostCoordinations,我尝试了Carrier和LayoutRoot的各种组合,但返回的元素总是空的

我做错了什么?你退房了吗?如果您在使用visualtreehelper时遇到问题,可以尝试一下

-编辑-


另外,您可能应该在e.GetPosition()调用中使用与在VisualTreeHelper.FindElementsInHostCoordinates()调用中使用相同的元素,但我想您已经尝试过了?

关于命中测试,您必须注意以下几点:

  • 没有背景的元素不会出现在命中测试中,因此设置背景,甚至将其设置为透明工作。发生这种情况是因为对象需要是“实体”以进行命中测试
  • 没有宽度和高度的元素不会出现在命中测试中,因为它们没有要命中的实体
  • IshittesVisible=false的元素不会出现在命中测试中,它们已被明确排除在命中测试之外
  • 在您的情况下,这些因素的组合使您的用户控件对命中测试不可见:

  • 您的用户控件不是实心的,它没有背景
  • 在用户控件中用作布局根的画布没有大小集,因此宽度和高度为零。它也没有背景
  • 用户控件中的所有子元素都具有ishitestvisible=false,这将它们明确地从命中测试中排除
  • 我对您的用户控件XAML和代码进行了一些修改,现在我在命中测试结果中看到了您的用户控件:

        public MainPage()
        {
            // Required to initialize variables
            InitializeComponent();
    
            var uiElement = new MyUserControl();
            this.Carrier.Children.Add(uiElement);
    
            MouseLeftButtonDown += MouseLeftButtonDownHandler;
        }
        private List<UIElement> HitSprite(Point p)
        {
            var hitElements =
               VisualTreeHelper.FindElementsInHostCoordinates(p, this.LayoutRoot) as List<UIElement>;
    
            return hitElements.Count > 0 ? hitElements : null;
        }
    
        private void MouseLeftButtonDownHandler(object sender, MouseButtonEventArgs e)
        {
            var list = HitSprite(e.GetPosition(this.LayoutRoot));
        }
    
    public主页()
    {
    //需要初始化变量
    初始化组件();
    var uiElement=new MyUserControl();
    this.Carrier.Children.Add(uiElement);
    MouseLeftButtonDown+=MouseLeftButtonDownHandler;
    }
    私有列表HitSprite(点p)
    {
    var hitElements=
    VisualTreeHelper.FindElementsInHostCoordinates(p,this.LayoutRoot)作为列表;
    返回hitElements。计数>0?hitElements:null;
    }
    私有void MouseLeftButtonDownHandler(对象发送器,MouseButtonEventArgs e)
    {
    var list=HitSprite(e.GetPosition(this.LayoutRoot));
    }
    
    XAML:

    
    

    作为一个额外的建议,嵌套画布面板不是一个好主意,除非有特定的理由这样做。画布在许多方面都是一个特殊的面板,例如,它不会剪裁超出其边界的项目,默认情况下它没有大小,除非您设置一个,并且除非您显式设置背景,否则它不是实体对象。尝试使用Grid和StackPanel来排列对象,并仅在(x,y)坐标上使用画布进行特定定位。

    顺便问一下,您使用的是silverlight还是wpf?UIElement.InputHitTest仅在wpf im Afraid中可用。我尝试了LayoutRoot和Carrier的各种组合,但没有任何运气。我用的是SL4。
    <Grid x:Name="Container" AllowDrop="True" Background="Transparent">
        <StackPanel Name="Description" Height="65" Canvas.ZIndex="2" IsHitTestVisible="False">
            <TextBlock Text="Testing" x:Name="Name" FontSize="12" FontWeight="Bold" HorizontalAlignment="Center" IsHitTestVisible="False"/>
    
            <Border Background="Green">
                <Image x:Name="Body" Stretch="None" Canvas.ZIndex="0" Height="20" Width="20">
                </Image>
            </Border>
        </StackPanel>
    </Grid>