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

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

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

要求:

  1. ItemsControl ItemsPanelTemplate 必须是 Canvas,大小不能为 0。
  2. 每个形状都可以随时点击,无需在可点击形状上激活 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 我应该可以点击任何形状。所以上面的项目也很重要,不容忽视。

标签: c# .net wpf


【解决方案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。
  • 这不是很难实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
  • 2011-08-31
  • 1970-01-01
相关资源
最近更新 更多