在 WPF 图像控件之上绘制
Draw Ontop Of Image Control In WPF
我正在努力将旧的 WinForms 项目移植到 WPF,但遇到了障碍。在这个旧的 WinForms 项目中,我使用每秒绘制图像的图片控件。除此之外,我还覆盖了控件 'Paint' 事件,以便在图像已设置后在图像顶部绘制自定义内容。
例如我的代码流程是这样的:
private void timer1_Tick(object sender, System.EventArgs e)
{
pictureBox1.Load("some/image/path");
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
// do custom drawing on top of the picture here..
}
WPF 不提供直接的 'Paint' 事件,所以我不确定我应该如何将其正确移植到 WPF 并仍然保持 MVVM 模式。
所以我的问题是:
- 使用图像控件是否适合此设置?
- 我应该如何在 WPF 中重新创建这个类似的设置,我可以根据需要更新图像,然后在其上绘制东西。
我的意图是保持传统的 MVVM 模式,但仍然能够在图像加载后绘制到图像上。所有绘图都是从应用程序内部完成的,没有用户与绘图交互。我基本上是在地图图像上实时绘制带有兴趣点的地图。地图是静态的,没有像 Google 的图块那样分成几块,所以我直接从磁盘加载没有问题。
好吧,经过大量的修改,我想出了一个适合我需要的方法。使用 canvas 控件并将其公开到我的视图模型,我可以将各种对象绘制到 canvas 以复制绘图的 WinForm 样式。
因此,对于寻找类似解决方法的其他人,我推荐 canvas 控件。
在干净的 MVVM 方法中,您可以使用带有 Canvas 作为 ItemsPanel
的 ItemsControl 和 ItemTemplate
中的路径控件。 Path 控件绑定到一组适当的视图模型属性,这些属性定义绘图的视觉外观。
<ItemsControl ItemsSource="{Binding Drawings}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Data="{Binding Geometry}"
Fill="{Binding Fill}"
Stroke="{Binding Stroke}"
StrokeThickness="{Binding StrokeThickness}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
视图模型可能是这样的:
public class Drawing
{
public Geometry Geometry { get; set; }
public Brush Fill { get; set; }
public Brush Stroke { get; set; }
public double StrokeThickness { get; set; }
}
public class ViewModel
{
public ObservableCollection<Drawing> Drawings { get; set; }
}
可以像下面这样使用。
public MainWindow()
{
InitializeComponent();
var vm = new ViewModel();
vm.Drawings = new ObservableCollection<Drawing>();
vm.Drawings.Add(new Drawing
{
Geometry = new EllipseGeometry(new Point(100, 100), 50, 30),
Fill = Brushes.LightBlue,
Stroke = Brushes.Blue,
StrokeThickness = 2
});
vm.Drawings.Add(new Drawing
{
Geometry = new RectangleGeometry(new Rect(50, 150, 100, 60)),
Fill = Brushes.LightGreen,
Stroke = Brushes.Green,
StrokeThickness = 2
});
DataContext = vm;
}
我正在努力将旧的 WinForms 项目移植到 WPF,但遇到了障碍。在这个旧的 WinForms 项目中,我使用每秒绘制图像的图片控件。除此之外,我还覆盖了控件 'Paint' 事件,以便在图像已设置后在图像顶部绘制自定义内容。
例如我的代码流程是这样的:
private void timer1_Tick(object sender, System.EventArgs e)
{
pictureBox1.Load("some/image/path");
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
// do custom drawing on top of the picture here..
}
WPF 不提供直接的 'Paint' 事件,所以我不确定我应该如何将其正确移植到 WPF 并仍然保持 MVVM 模式。
所以我的问题是:
- 使用图像控件是否适合此设置?
- 我应该如何在 WPF 中重新创建这个类似的设置,我可以根据需要更新图像,然后在其上绘制东西。
我的意图是保持传统的 MVVM 模式,但仍然能够在图像加载后绘制到图像上。所有绘图都是从应用程序内部完成的,没有用户与绘图交互。我基本上是在地图图像上实时绘制带有兴趣点的地图。地图是静态的,没有像 Google 的图块那样分成几块,所以我直接从磁盘加载没有问题。
好吧,经过大量的修改,我想出了一个适合我需要的方法。使用 canvas 控件并将其公开到我的视图模型,我可以将各种对象绘制到 canvas 以复制绘图的 WinForm 样式。
因此,对于寻找类似解决方法的其他人,我推荐 canvas 控件。
在干净的 MVVM 方法中,您可以使用带有 Canvas 作为 ItemsPanel
的 ItemsControl 和 ItemTemplate
中的路径控件。 Path 控件绑定到一组适当的视图模型属性,这些属性定义绘图的视觉外观。
<ItemsControl ItemsSource="{Binding Drawings}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Path Data="{Binding Geometry}"
Fill="{Binding Fill}"
Stroke="{Binding Stroke}"
StrokeThickness="{Binding StrokeThickness}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
视图模型可能是这样的:
public class Drawing
{
public Geometry Geometry { get; set; }
public Brush Fill { get; set; }
public Brush Stroke { get; set; }
public double StrokeThickness { get; set; }
}
public class ViewModel
{
public ObservableCollection<Drawing> Drawings { get; set; }
}
可以像下面这样使用。
public MainWindow()
{
InitializeComponent();
var vm = new ViewModel();
vm.Drawings = new ObservableCollection<Drawing>();
vm.Drawings.Add(new Drawing
{
Geometry = new EllipseGeometry(new Point(100, 100), 50, 30),
Fill = Brushes.LightBlue,
Stroke = Brushes.Blue,
StrokeThickness = 2
});
vm.Drawings.Add(new Drawing
{
Geometry = new RectangleGeometry(new Rect(50, 150, 100, 60)),
Fill = Brushes.LightGreen,
Stroke = Brushes.Green,
StrokeThickness = 2
});
DataContext = vm;
}