使用ItemsControl时如何将X / Y位置转换为Canvas Left / Top属性 [英] How to convert X/Y position to Canvas Left/Top properties when using ItemsControl
问题描述
我正在尝试使用画布来显示具有世界位置的对象(而不是屏幕位置)。画布定义如下:
I am trying to use a Canvas to display objects that have "world" location (rather than "screen" location). The canvas is defined like this:
<Canvas Background="AliceBlue">
<ItemsControl Name="myItemsControl" ItemsSource="{Binding MyItems}">
<Image x:Name="myMapImage" Panel.ZIndex="-1" />
<ItemsControl.ItemTemplate>
<DataTemplate>
<Canvas>
<TextBlock Canvas.Left="{Binding WorldX}" Canvas.Top="{Binding WorldY}"
Text="{Binding Text}"
Width="Auto" Height="Auto" Foreground="Red" />
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
MyItem定义如下:
MyItem is defined like this:
public class MyItem
{
public MyItem(double worldX, double worldY, string text)
{
WorldX = worldX;
WorldY = worldY;
Text = text;
}
public double WorldX { get; set; }
public double WorldY { get; set; }
public string Text { get; set; }
}
此外,我还有一种在世界和屏幕坐标之间进行转换的方法:
In addition, I have a method to convert between world and screen coordinates:
Point worldToScreen(double worldX, double worldY)
{
// Note that the conversion uses an internal m_mapData object
var size = m_mapData.WorldMax - m_mapData.WorldMin;
var left = ((worldX - m_currentMap.WorldMin.X) / size.X) * myMapImage.ActualWidth;
var top = ((worldY - m_currentMap.WorldMin.Y) / size.Y) * myMapImage.ActualHeight;
return new Point(left, top);
}
随着当前的实现,项目位于错误的位置,因为他们位置不会转换为屏幕坐标。
With the current implementation, the items are positioned in the wrong location, because their location is not converted to screen coordinates.
在MyItem对象添加到画布之前,如何应用worldToScreen方法?
How can I apply the worldToScreen method on the MyItem objects before they are added to the canvas?
我有一点困惑我是否以正确的方式进行,所以我发布了另一个问题:如何使用WPF可视化一个简单的2D世界(地图和元素)
I got a little confused whether I'm going in the right way, so I posted another question: How to use WPF to visualize a simple 2D world (map and elements)
对于这个问题,还有一个有用和完整的答案
There is a helpful and complete answer there also for this question
推荐答案
您提供的代码的主要问题是 Canvas.Left
和 Canvas.Top
属性是相对于 Canvas
,位于 DataTemplate
for ItemsCon trol
。这将保持重置原点。而您可以:
The main problem with the code you presented is that the Canvas.Left
and Canvas.Top
properties are relative to a Canvas
that is in the DataTemplate
for the ItemsControl
. This keeps "resetting" the origin. Instead you can:
- 从
中删除
Canvas
为ListBox
ItemsPanel > $ - 将
ItemsPresenter
放在ItemsControl
具有的项目Canvas.Top
和Canvas.Left
- 确保
Image
和Canvas
具有相同的坐标,或切换到使用画布
Canvas
- remove the
Canvas
from theDataTemplate
- make the
ItemsPanel
for theListBox
aCanvas
- position the
ItemsPresenter
that wraps theItemsControl
items withCanvas.Top
andCanvas.Left
- ensure that the
Image
and theCanvas
have the same coordinates, or switch to using the `Canvas
这是一个完整的XAML唯一的例子,定位 ItemsControl
Canvas
在 Canvas
之后的图像
p>
Here is a complete XAML-only example of positioning ItemsControl
items on a Canvas
with an Image
behind the Canvas
:
<Grid>
<Image x:Name="image" Height="100" Width="Auto" Source="http://thecybershadow.net/misc/stackoverflow.png"/>
<ItemsControl Name="myItemsControl">
<ItemsControl.ItemsSource>
<PointCollection>
<Point X="10" Y="10"/>
<Point X="30" Y="30"/>
</PointCollection>
</ItemsControl.ItemsSource>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="Text" Foreground="Red"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
这篇关于使用ItemsControl时如何将X / Y位置转换为Canvas Left / Top属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!