使用ItemsControl时如何将X/Y位置转换为Canvas Left/Top属性

ksh*_*har 4 data-binding wpf itemscontrol coordinates

我试图使用Canvas显示具有"世界"位置(而不是"屏幕"位置)的对象.画布定义如下:

<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>
Run Code Online (Sandbox Code Playgroud)

MyItem的定义如下:

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; }
}
Run Code Online (Sandbox Code Playgroud)

另外,我有一种在世界和屏幕坐标之间进行转换的方法:

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);
}
Run Code Online (Sandbox Code Playgroud)

使用当前实现,项目位于错误的位置,因为它们的位置未转换为屏幕坐标.

如何在将MyTtem对象添加到画布之前对其应用worldToScreen方法?


编辑:

我有点困惑,我是否正确的方式,所以我发布了另一个问题:如何使用WPF可视化一个简单的2D世界(地图和元素)

对于这个问题,还有一个有用且完整的答案

Ric*_*key 7

你给出的代码的主要问题是,Canvas.LeftCanvas.Top属性是相对于一个Canvas那就是在DataTemplateItemsControl.这样可以"重置"原点.相反,你可以:

  • Canvas从中删除DataTemplate
  • ItemsPanelListBox一个Canvas
  • 定位用和ItemsPresenter包裹ItemsControl物品Canvas.TopCanvas.Left
  • 确保ImageCanvas具有相同的坐标,或切换到使用"画布"

这是定位的一个完整的唯一XAML的例子ItemsControl在一个项目Canvas有一个Image背后的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>
Run Code Online (Sandbox Code Playgroud)