После размещения элемента 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 myEllipse = (Ellipse)sender; но я не вижу никакой собственности, которая содержит информацию.

Если я использую GeneralTransform gt = myEllipse.TransformToVisual(Application.Current.RootVisual); он дает мне только Transform относительно RootVisual, а не сетки, на которой я рисую.

Возможно, я пропускаю что-то очевидное здесь. Буду благодарен за любую подсказку.

2 ответа

Решение

Я нашел решение. Чтобы получить преобразование 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));
    }

Я не совсем уверен, в чем твоя проблема, но, думаю, я понял.

Вы используете очень странный подход к позиционированию предметов в 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 Событие будет запущено только тогда, когда пользователь щелкнет сам элемент, и вам не нужно будет рассчитывать позиции выбранных элементов.

Другие вопросы по тегам