我使用ItemsControl将集合中的项目定位在画布上。定位是通过TranslateTransform:<TranslateTransform X="{Binding x}" Y="{Binding y}"/>
完成的。为了使这些项目可点击,我在这些项目上实现了MouseLeftButtonUp事件。
请参阅下面的完整代码:
<ItemsControl ItemsSource="{Binding XYPoints}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Width="20" Height="20" Fill="Red" MouseLeftButtonUp="XYPlotPoint_MouseLeftButtonUp">
<Ellipse.RenderTransform>
<TransformGroup>
<RotateTransform Angle="0"/>
<TranslateTransform X="{Binding x}" Y="{Binding y}"/>
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse >
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
我无法理解的是:我希望能够点击我的任何项目并获得TranslateTransform坐标,即用于在画布上定位元素的x和y值。
我的想法是在将发送方强制转换回Ellipse(例如Ellipse myEllipse = (Ellipse)sender;
)后,从事件的发送方获得此信息,但我看不到任何包含该信息的属性。
如果我使用GeneralTransform gt = myEllipse.TransformToVisual(Application.Current.RootVisual);
,它只会给我相对于RootVisual的转换,而不是相对于我正在绘制的网格。
也许我忽略了一些显而易见的东西。如果有任何提示,我将不胜感激。
我不太确定你的问题是什么,但我想我已经解决了。
您正在使用一种非常奇怪的方法在Canvas
中定位项目。正是你的方法让点击支持变得如此困难。你只是让你所有的物品相互叠加。您只需在不同的位置渲染它们,而布局和输入系统则认为所有项目都位于坐标系原点。这就是为什么所有鼠标事件都不起作用。
主流方法是通过其附加的属性Canvas.Left
和Canvas.Top
,如MSDN中所示。尝试通过ItemContainerStyle
:绑定属性
<ItemsControl ItemsSource="{Binding XYPoints}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Width="20" Height="20" Fill="Red" MouseLeftButtonUp="XYPlotPoint_MouseLeftButtonUp"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.X" Value="{Binding x, Mode=TwoWay}"/>
<Setter Property="Canvas.Y" Value="{Binding y, Mode=TwoWay}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
一旦你这样做了,你的MouseLeftButtonUp
事件将只在用户点击该项目时被触发,并且你不需要计算点击项目的位置。
我找到了解决方案。要获得单击的UIElement
(我的项目)相对于另一个UIElement
(在我的情况下是它所在的Grid
,也是LayoutRoot
)的转换:
private void XYPlotPoint_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//cast sender to original type
Ellipse myEllipse = (Ellipse)sender;
//get the transform relative to the LayoutRoot
GeneralTransform gt = myEllipse.TransformToVisual(LayoutRoot);
//transform a new point to get the coordinates
var myUiElementPosition = gt.Transform(new Point(0, 0));
}