Canvas 有线和点

Canvas with Lines and Points

我正在迁移旧应用程序并尝试实施 MVVM。旧应用程序的界面与描述的界面相似 in this post。虽然稍微简单了点。我不太担心完全遵循 MVVM,但我想借此机会练习。

我有以下 class:

public class LineViewModel
{
    public ObservableCollection<LinePoint> Points {get;}
    public Geometry LineGeometry {get;}
}

在我的应用程序视图模型中,我有一组线条,我想在 Canvas 上绘制这些线条,但我也想绘制构成每条线条的点。

到目前为止,这是我的 XAML:

<ItemsControl ItemsSource="{Binding Lines}">
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type local:LineViewModel}">
            <Path StrokeThickness="2.0" Stroke="Black" Data="{Binding LineGeometry}" />
        </DataTemplate>

        <DataTemplate DataType="{x:Type local:LinePoint}">
            <Ellipse StrokeThickness="1.0" Stroke="Black" Fill="MistyRose" Width="8.0" Height="8.0" />
        </DataTemplate>
    </ItemsControl.Resources>

    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

我可以看到正在绘制的线条,这似乎工作正常。如您所见,我已经为点添加了模板,但我不知道如何设置 XAML 来绘制这些点。我怎样才能画出这些点?

从直线中提取点并从应用程序视图模型中公开这些点似乎有违直觉,因为是 LineViewModel 负责处理直线中的点,而不是应用程序。如果可以的话,我宁愿不把点和线分开。

谢谢

我建议创建一个视图模型,其中一个 属性 用于线的点

class LineViewModel
{
    public PointCollection LinePoints { get; set; }
}

class ViewModel
{
    public IEnumerable<LineViewModel> Lines { get; set; }
}

然后您可以在 "outer" ItemsControl 的 DataTemplate 中有一个嵌套的 ItemsControl,如下所示,它使用 Polyline 来绘制线条和 Path 元素的集合EllipseGeometries 为圈子。

<ItemsControl ItemsSource="{Binding Lines}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Canvas>
                <Polyline Points="{Binding LinePoints}"
                          StrokeThickness="2.0" Stroke="Black"/>

                <ItemsControl ItemsSource="{Binding LinePoints}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <Canvas/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>

                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Path StrokeThickness="1.0" Stroke="Black" Fill="MistyRose">
                                <Path.Data>
                                    <EllipseGeometry Center="{Binding}"
                                                     RadiusX="4" RadiusY="4"/>
                                </Path.Data>
                            </Path>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </Canvas>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

如果您必须按原样使用 LineViewModel,您可以编写如下所示的 ItemTemplate,使用绑定转换器将 LinePoint 转换为 Point 以用于 Center的 EllipseGeometry。

<ItemsControl.ItemTemplate>
    <DataTemplate>
        <Canvas>
            <Path StrokeThickness="2.0" Stroke="Black" Data="{Binding LineGeometry}" />

            <ItemsControl ItemsSource="{Binding Points}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>

                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Path StrokeThickness="1.0" Stroke="Black" Fill="MistyRose">
                            <Path.Data>
                                <EllipseGeometry
                                    Center="{Binding
                                        Converter={StaticResource LinePointConverter}}"
                                    RadiusX="4" RadiusY="4"/>
                            </Path.Data>
                        </Path>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Canvas>
    </DataTemplate>
</ItemsControl.ItemTemplate>