如何捕捉鼠标点击事件到重叠的ItemsControl

Posted

技术标签:

【中文标题】如何捕捉鼠标点击事件到重叠的ItemsControl【英文标题】:How To Catch Mouse Click Event To Overlapped ItemsControl 【发布时间】:2016-06-03 15:25:16 【问题描述】:

我想开发一种使用 WPF 的矢量图像编辑器。 具有相同形式的每个形状都放置在 ItemsControl 中。 至少有 4 种形状(线、矩形、位图等)。 问题是:

我无法单击另一层下方的形状。

要求:

    ItemsControl ItemsPanelTemplate 必须是 Canvas,大小不能为 0。 每个形状都可以随时点击,无需在可点击形状上激活 IsHitTestVisible。

问题:

如何在上方的 ItemsControl 中启用单击其他形状下方的形状?

编辑 1: 添加代码sn-p

<Grid>
    <!--Array of Ellipses-->
    <ItemsControl ItemsSource="Binding EllipseSource">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left" Value="Binding Path=Distance" />
                <Setter Property="Canvas.Width" Value="10" />
                <Setter Property="Canvas.Top" Value="Binding Path=Top" />
                <Setter Property="Canvas.Height" Value="10" />
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <Ellipse MouseDown="EllipseOnMouseDown" />
        </ItemsControl.ItemTemplate>
    </ItemsControl>

    <!--Array of Rectangles-->
    <ItemsControl ItemsSource="Binding RectangleSource">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left" Value="Binding Path=Distance" />
                <Setter Property="Canvas.Width" Value="10" />
                <Setter Property="Canvas.Top" Value="Binding Path=Top" />
                <Setter Property="Canvas.Height" Value="10" />
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <Rectangle MouseDown="RectangleOnMouseDown" />
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

【问题讨论】:

那么有两个重叠项,你想只获得较低项的点击事件,忽略较高项? 您在寻找Panel.ZIndex 附件MSDN @Gopichandar Panel.ZIndex 更改形状隐藏其他形状的方式,这些形状相互重叠。 类似this。也许您可以根据事件使ZIndex 动态化。 @Sakura 我应该可以点击任何形状。所以上面的项目也很重要,不容忽视。 【参考方案1】:

注意:

将您的 Grid 控件命名为 grid 将您的函数 RectangleOnMouseDownEllipseOnMouseDown 更改为 shape_MouseLeftButtonDown

您可以使用: XAML:

<Grid name="grid">
    <!--Array of Ellipses-->
    <ItemsControl ItemsSource="Binding EllipseSource">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left" Value="Binding Path=Distance" />
                <Setter Property="Canvas.Width" Value="10" />
                <Setter Property="Canvas.Top" Value="Binding Path=Top" />
                <Setter Property="Canvas.Height" Value="10" />
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <Ellipse MouseDown="shape_MouseLeftButtonDown" />
        </ItemsControl.ItemTemplate>
    </ItemsControl>

    <!--Array of Rectangles-->
    <ItemsControl ItemsSource="Binding RectangleSource">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left" Value="Binding Path=Distance" />
                <Setter Property="Canvas.Width" Value="10" />
                <Setter Property="Canvas.Top" Value="Binding Path=Top" />
                <Setter Property="Canvas.Height" Value="10" />
            </Style>
        </ItemsControl.ItemContainerStyle>
        <ItemsControl.ItemTemplate>
            <Rectangle MouseDown="shape_MouseLeftButtonDown" />
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

代码:

List<DependencyObject> hitResultsList = new List<DependencyObject>();

// Return the result of the hit test to the callback.
public HitTestResultBehavior MyHitTestResult(HitTestResult result)

    hitResultsList.Add(result.VisualHit);
    return HitTestResultBehavior.Continue;


private void shape_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

    Point pt = Mouse.GetPosition(grid);
    hitResultsList.Clear();
    VisualTreeHelper.HitTest(grid, null, new HitTestResultCallback(MyHitTestResult), new PointHitTestParameters(pt));

    foreach (var ee in hitResultsList)
    
        if(ee is Ellipse)
        
            MessageBox.Show("rectangle clicked!");
            var ellipse = ee as Ellipse;
            // Do something with ellipse
        
        if(ee is Rectangle)
        
            MessageBox.Show("ellipse clicked!");
            var rec = ee as Rectangle;
            // Do something with rectangle
        

    

【讨论】:

好主意,鼠标问题解决了,但问题是其他控件下的控件的WPF功能仍然丢失。例如,如果 Rectangle 和 Ellipse 下面的 Ellipse 具有其他 WPF 控件,例如 TextBox。 f 鼠标光标在 Ellips 上方,鼠标光标不会变为文本输入光标,也不能直接编辑 TextBox。但我会用不同的方法使用你的解决方案。取而代之的是 MouseLeftButtonDown 事件,我将使用 MouseMove 事件,如果鼠标光标下方有一个椭圆,那么它的 ItemsControl.IsHitTestVisible =true 和其他 ItemsControl.IsHitVisible=false。 这不是很难实现。

以上是关于如何捕捉鼠标点击事件到重叠的ItemsControl的主要内容,如果未能解决你的问题,请参考以下文章

捕捉鼠标事件

如何使绝对定位的图像区域地图可以用鼠标点击?

winform中键盘和鼠标事件的捕捉和重写

用C# winForm,一个pannel容器上有许多label,怎样才能使得鼠标点击label时触发的pannel事件呢?

如何在Android应用里屏蔽鼠标点击事件

NativeScript:如果用户点击 RadListView 中的空白空间,我如何捕捉点击事件?