【问题标题】:WPF draw lines between elements on canvas in a itemscontrolWPF在itemscontrol中画布上的元素之间绘制线条
【发布时间】:2021-01-26 22:29:52
【问题描述】:

我想在 itemscontrol 中的多个椭圆之间画线。

最终结果应该是这样的。

问题是所有的圆圈都是在运行时绘制的。它们位于 itemscontrol 中,其代码如下所示。

<ItemsControl x:Name="SpaceObjectsIC"
                      Grid.Row="0" Grid.Column="0"
                      ItemsSource="{Binding SpaceObjects, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas Background="LightGray" Width="800" Height="600" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Ellipse Fill="{Binding Color, Converter={StaticResource ColorConverter}}"
                             Stroke="{Binding Border, Converter={StaticResource ColorConverter}}" 
                             StrokeThickness="{Binding BorderThickness}"
                             Height="{Binding Diameter}" Width="{Binding Diameter}" Tag="{Binding Name}"
                             ClipToBounds="True">
                        <Ellipse.RenderTransform>
                            <TranslateTransform X="{Binding X}" Y="{Binding Y}" />
                        </Ellipse.RenderTransform>
                    </Ellipse>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

如您所见,我使用的数据模板只能使用一个元素。我不知道如何在 XAML 中解释我想在这些特定的椭圆之间画线。

只有所谓的“邻居”圈子才需要线条。如果您查看 xaml,您会看到绑定了一个名为 SpaceObjects 的列表。每个有邻居的空间物体都知道这些邻居(它们也是空间物体)。这意味着找到圆圈的 x 和 y 位置很容易。 我只是不知道如何在不破坏 MVVM 规则的情况下动态地在它们之间绘制这些线,而且我也不想在后面使用代码。

xaml 的数据上下文是一个名为 SpaceViewModel 的 clise,其中包含一个带有空间对象的 ObservableCollection。

SpaceObject 代码如下所示(我省略了属性,但只知道它们确实存在):

public class SpaceObject : ISpaceObject, INotifyPropertyChanged
{
    private decimal _x;
    private decimal _y;
    private List<SpaceObject> _spaceNeighbours = new List<SpaceObject>();
}

既然我已经获得了我需要的所有数据,我该如何让 Xaml 做我想做的事?

【问题讨论】:

  • 我认为,您的点(井圈)和线需要单独的 VM。它们可以表示为模型中的点和邻居,但如果有的话,处理视图会更容易,为您的线和点分隔对象(因为它们在视觉上是不同的)。具有更多 XAML 专业知识的人可能会找到一种方法来使用您当前的结构,但我当然没有专业知识

标签: c# wpf xaml path line


【解决方案1】:

从您的 itemssource 绑定中删除 , UpdateSourceTrigger=PropertyChanged。

使 SpaceObjects 成为 ObservableCollection

将您当前的数据模板移动到项目控件的资源中。使用 Datatemplate DataType="{x:Type YourPlanetVM}"

将其与您当前的视图模型类型相关联

定义一个新的视图模型,其属性指定线开始 X 和 Y 以及结束 X 和 Y。

计算 x 和 y 开始和结束,并在这些视图模型上设置它们。 首先将这些添加到 observablecollection,因为这会影响 z-index。大概是你想要你的线在行星下面。

使用 ItemContainerStyle 定位行星

  <ItemsControl.ItemContainerStyle>
         <Style>
              <Setter Property="Canvas.Top" Value="{Binding X}"/>
              <Setter Property="Canvas.Left" Value="{Binding Y}"/>

您的 LineVM 需要将这些设置为 0 它还需要绑定到 Line 的属性:

https://docs.microsoft.com/en-us/dotnet/api/system.windows.shapes.line?view=netcore-3.1

您将需要一个 linevm 的数据模板,其中包含开始和结束 x,y 以及笔触(画笔)和笔触厚度。

我建议为您的路径使用椭圆几何。这以 X、Y 坐标为中心,而不是位于左上角。类似这样的数据模板(但带有一些硬编码值)如下所示:

                                    <Path  
                                                Height="2"
                                                Width="2"
                                                Fill="Black">
                                        <Path.Data>
                                            <EllipseGeometry 
                                                            RadiusX="1" 
                                                            RadiusY="1"
                                                                       />
                                        </Path.Data>
                                    </Path>

【讨论】:

  • 我知道我必须避免使用这些 cmets,因为 stackoverflow 不喜欢它,但我只是想说声谢谢!不仅解决了我的问题,还让一切看起来更好:D
猜你喜欢
  • 2010-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-19
  • 2021-12-14
  • 1970-01-01
相关资源
最近更新 更多