使用ItemsControl时如何将X / Y位置转换为Canvas Left / Top属性 [英] How to convert X/Y position to Canvas Left/Top properties when using ItemsControl

查看:158
本文介绍了使用ItemsControl时如何将X / Y位置转换为Canvas Left / Top属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用画布来显示具有世界位置的对象(而不是屏幕位置)。画布定义如下:

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
  • > $ Canvas
  • ItemsPresenter 放在 ItemsControl 具有的项目Canvas.Top Canvas.Left

  • 确保 Image Canvas 具有相同的坐标,或切换到使用画布

  • remove the Canvas from the DataTemplate
  • make the ItemsPanel for the ListBox a Canvas
  • position the ItemsPresenter that wraps the ItemsControl items with Canvas.Top and Canvas.Left
  • ensure that the Image and the Canvas 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆