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