将ItemsControl项放置在画布上后,获取其Transform(Silverlight 5)



我使用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.LeftCanvas.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));
    }

最新更新