WPF 中的可编辑图形
Editable graphics in WPF
我正在开发一个向 window 显示复杂图形的 WPF 应用程序。我需要这些图形是高度动态的,这意味着例如线条可以随时出现、消失或只是移动(通过鼠标交互或以编程方式)。
有没有办法不用每次都重建完整的显示列表就可以实现?一个典型的例子是数据点可以移动但其余部分不能移动的函数图。这些点可能是即时计算的,而不是存储在数组中,因此参考它们的图形表示很棘手。
代码示例(根据要求):
// Add a Line Element
myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
myLine.X1 = 1;
myLine.X2 = 50;
myLine.Y1 = 1;
myLine.Y2 = 50;
myLine.HorizontalAlignment = HorizontalAlignment.Left;
myLine.VerticalAlignment = VerticalAlignment.Center;
myLine.StrokeThickness = 2;
myGrid.Children.Add(myLine);
更新:
假设我绘制了三个函数。我画了轴、图例、刻度线……和三条曲线。
如果我想删除第二条曲线,现在有比重绘一切更好的方法吗?
我发现 DrawingGroup
class 部分满足了我的需求,因为它允许对图形实体进行分组并将它们作为一个整体来处理。不管怎样,还是得跟踪每一组,才能分别编辑。
万一使用 DrawingVisual
而不是 Canvas
,GeometryGroup
也很方便。
Is there a way to achieve that without rebuilding the complete display list every time ?
这正是一般的 MVVM 模式和 WPF 模板一起旨在提供的。具体来说,除了这个之外,你没有描述你想要实现的大部分目标:
lines can appear, disappear or just be moved at any time
对我来说,这听起来像是两个模型 类,一个用于点(X
和 Y
坐标),一个用于线(包含对两个点的引用)。点模型是可观察的(即它实现 INotifyPropertyChanged
正确和完整),而线模型应该永远不会改变。
对于您的视图模型,您拥有的是 collection 个实体(类似 IEntity
),这两个模型都是从中派生的。所以只是一个 ObservableCollection<IEntity>
类型的只读 属性。当您想从一条线上移动一个点时,只需更新其 X
and/or Y
坐标即可。要添加一行吗?将点和连接它们的线添加到您的 collection。删除也一样。简单!
最后一部分,您的看法。这包含一个绑定到您的视图模型 collection 的 ItemsControl
,面板模板设置为 <Canvas/>
(以便能够直接设置位置)和 <DataTemplate>
资源,每个资源一个您拥有的模型类型:
- 线条很简单,只需将它们的四个位置属性绑定到线模型中两个点模型的
X
和 Y
坐标即可绘制到位。
- 点是你喜欢的地方,它们的目的是提供操纵器来移动它们,即响应拖动事件并更新其绑定属性的用户控件。因为线条包含对您的点的引用,所以直接更新点将在视觉上重新定位受影响的点以及连接它的线。
我正在开发一个向 window 显示复杂图形的 WPF 应用程序。我需要这些图形是高度动态的,这意味着例如线条可以随时出现、消失或只是移动(通过鼠标交互或以编程方式)。
有没有办法不用每次都重建完整的显示列表就可以实现?一个典型的例子是数据点可以移动但其余部分不能移动的函数图。这些点可能是即时计算的,而不是存储在数组中,因此参考它们的图形表示很棘手。
代码示例(根据要求):
// Add a Line Element
myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
myLine.X1 = 1;
myLine.X2 = 50;
myLine.Y1 = 1;
myLine.Y2 = 50;
myLine.HorizontalAlignment = HorizontalAlignment.Left;
myLine.VerticalAlignment = VerticalAlignment.Center;
myLine.StrokeThickness = 2;
myGrid.Children.Add(myLine);
更新:
假设我绘制了三个函数。我画了轴、图例、刻度线……和三条曲线。
如果我想删除第二条曲线,现在有比重绘一切更好的方法吗?
我发现 DrawingGroup
class 部分满足了我的需求,因为它允许对图形实体进行分组并将它们作为一个整体来处理。不管怎样,还是得跟踪每一组,才能分别编辑。
万一使用 DrawingVisual
而不是 Canvas
,GeometryGroup
也很方便。
Is there a way to achieve that without rebuilding the complete display list every time ?
这正是一般的 MVVM 模式和 WPF 模板一起旨在提供的。具体来说,除了这个之外,你没有描述你想要实现的大部分目标:
lines can appear, disappear or just be moved at any time
对我来说,这听起来像是两个模型 类,一个用于点(X
和 Y
坐标),一个用于线(包含对两个点的引用)。点模型是可观察的(即它实现 INotifyPropertyChanged
正确和完整),而线模型应该永远不会改变。
对于您的视图模型,您拥有的是 collection 个实体(类似 IEntity
),这两个模型都是从中派生的。所以只是一个 ObservableCollection<IEntity>
类型的只读 属性。当您想从一条线上移动一个点时,只需更新其 X
and/or Y
坐标即可。要添加一行吗?将点和连接它们的线添加到您的 collection。删除也一样。简单!
最后一部分,您的看法。这包含一个绑定到您的视图模型 collection 的 ItemsControl
,面板模板设置为 <Canvas/>
(以便能够直接设置位置)和 <DataTemplate>
资源,每个资源一个您拥有的模型类型:
- 线条很简单,只需将它们的四个位置属性绑定到线模型中两个点模型的
X
和Y
坐标即可绘制到位。 - 点是你喜欢的地方,它们的目的是提供操纵器来移动它们,即响应拖动事件并更新其绑定属性的用户控件。因为线条包含对您的点的引用,所以直接更新点将在视觉上重新定位受影响的点以及连接它的线。