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?
Edit:
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.LeftandCanvas.Topproperties are relative to aCanvasthat is in theDataTemplatefor theItemsControl. This keeps “resetting” the origin. Instead you can:Canvasfrom theDataTemplateItemsPanelfor theListBoxaCanvasItemsPresenterthat wraps theItemsControlitems withCanvas.TopandCanvas.LeftImageand theCanvashave the same coordinates, or switch to using the `CanvasHere is a complete XAML-only example of positioning
ItemsControlitems on aCanvaswith anImagebehind theCanvas: