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 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.
How can I apply the worldToScreen method on the MyItem objects before they are added to the canvas?
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
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
from the DataTemplate
ItemsPanel
for the ListBox
a Canvas
ItemsPresenter
that wraps the ItemsControl
items with Canvas.Top
and Canvas.Left
Image
and the Canvas
have the same coordinates, or switch to using the `CanvasHere 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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With