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>
我正在迁移旧应用程序并尝试实施 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>