如何捕捉鼠标点击事件到重叠的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
将您的函数 RectangleOnMouseDown
和 EllipseOnMouseDown
更改为 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的主要内容,如果未能解决你的问题,请参考以下文章
用C# winForm,一个pannel容器上有许多label,怎样才能使得鼠标点击label时触发的pannel事件呢?