所以,我使用了winForms .CreateGraphics来绘制各种不同的东西,从线条到盒子再到图像。它非常活泼,反应灵敏。
我正在尝试用C#
学习WPF我发现WPF允许我将“矩形”对象“添加”到画布上,以便正确显示它们。然而,我有时会画出数十万个矩形,并且绘制速度会变得非常慢,当我移动一个矩形时,UI变得不那么活泼。
在winForms中直接绘制到一个元素上的速度并不是很快,但无论我绘制多少,它都是一致的。
在WPF中是否有类似的解决方案?
我尝试将linq添加到System.Drawing
,这给了我一个Graphics
对象,但我尝试过的wpf元素都没有.CreateGraphics()
方法。
答案 0 :(得分:4)
WPF使用与WinForms不同的图形处理模型。
使用WinForms,您可以直接编辑屏幕上的像素。绘制像素后,矩形的概念将丢失。绘制像素是一种非常快速的操作。
使用WPF,您无法控制屏幕上的像素。 DirectDraw是。 DirectDraw是一个基于矢量的合成引擎。你不绘制像素。您可以定义矢量形状(或视觉效果)。即使在将图像渲染到屏幕之后,形状或矩形的概念也是RETAINED。当您添加一个与其他矩形重叠的新矩形时,所有其他矩形都需要重新扫描。这可能是您的表现减慢的地方。使用WinForms时不会发生这种情况。
您可以通过覆盖OnRender来提高WPF的性能。您可以减少Rectangle对象的开销并直接提供视觉效果。但是,您仍然没有在屏幕上绘制像素。您正在定义DirectDraw用于渲染图像的形状。在这方面,OnRender名称可能有点误导。
我相信你可以找到很多技巧来提高你在WPF中的应用程序的性能。还有一些方法可以画出像素 - 但这有点类似于WPF。
你在做什么需要数千个矩形?
答案 1 :(得分:2)
您需要创建一个覆盖OnRender并在那里进行绘制的控件。没有办法让你绘制另一个控件,但控件可以绘制自己。
另外,请记住,WPF使用retained graphics,因此如果您更改了某些内容,则需要根据需要使视觉无效。
编辑:
类似的东西:
public class MyControl : Control {
public MyControl() {
this.Rects = new ObservableCollection<Rect>();
// TODO: attach to CollectionChanged to know when to invalidate visual
}
public ObservableCollection<Rect> Rects { get; private set; }
protected override void OnRender(DrawingContext dc) {
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Colors.LimeGreen;
Pen myPen = new Pen(Brushes.Blue, 10);
foreach (Rect rect in this.Rects)
dc.DrawRectangle(mySolidColorBrush, myPen, rect);
}
}
答案 2 :(得分:2)
如前所述,WPF使用保留的图形方法,因此您实际在内存中创建100,000个Rectangle对象,然后绘制所有这些对象。减速可能是由于垃圾收集和一般内存问题造成的。
除了覆盖OnRender方法之外,这里有一些你可以研究的事情。
使用熟悉的GDI方法将矩形绘制到后台线程中的图像,然后将结果写入WPF WriteableBitmap
使用D3DImage并利用硬件加速。这需要您了解DirectX(或Direct2D)库。如果您对此方法感兴趣,我建议您查看SlimDx。
答案 3 :(得分:2)
问题是最不可能的是,WPF无法渲染1000个图形对象,但是你创建和添加的项目太远了WPF对象的层次结构。它毕竟使用GPU进行所有图形化的工作。
您应该尽可能靠近“Visual”类添加对象,只要您开始添加基于后者“UIElement”的对象,您要求WPF跟踪每个对象的用户点击,悬停等,而不是只是画它。