8

因此,我使用 winForms .CreateGraphics 绘制了各种不同的东西,从线条到框再到图像。它非常活泼且反应灵敏。

我正在尝试在 C# 中学习 WPF

我发现 WPF 允许我将矩形对象“添加”到可以正确显示它们的画布上。但是,我有时会绘制数十万个矩形,并且绘制速度会变得非常缓慢,并且即使移动 1 个矩形,UI 也会变得不那么活泼。

直接在winForms中的元素上绘画不是很快,但无论我画多少都是一致的。

在 WPF 中是否有类似的解决方案?

我尝试添加一个 linq to System.Drawing,它给了我一个Graphics对象,但是我尝试的 wpf 元素都没有这个.CreateGraphics()方法。

4

4 回答 4

6

WPF 使用与 WinForms 不同的图形操作模型。

使用 WinForms,您可以直接编辑屏幕上的像素。绘制像素后,矩形的概念就丢失了。绘制像素是一种非常快速的操作。

使用 WPF,您无需控制屏幕上的像素。DirectDraw 是。DirectDraw 是一个基于矢量的合成引擎。您不绘制像素。您定义矢量形状(或视觉效果)。形状或矩形的概念是保留的,即使在图像被渲染到屏幕上之后也是如此。当您添加一个与其他矩形重叠的新矩形时,需要重新绘制所有其他矩形。这可能是您的性能下降的地方。使用 WinForms 时不会发生这种情况。

您可以通过重写 OnRender 来稍微提高 WPF 的性能。您可以削减 Rectangle 对象的开销并直接提供视觉效果。但是,您仍然没有在屏幕上绘制像素。您正在定义 DirectDraw 用于呈现图像的形状。在这方面,OnRender 名称可能有点误导。

我相信您可以在 WPF 中找到很多提高应用程序性能的技巧。仍然有一些方法可以绘制像素 - 但这有点违背 WPF 的观点。

你在做什么需要数千个矩形?

于 2011-05-11T18:14:14.537 回答
3

您需要创建一个覆盖OnRender的控件并在其中进行绘图。您无法在另一个控件上绘制,但控件可以绘制自己。

另外,请记住 WPF 使用保留图形,因此如果您更改某些内容,则需要根据需要使视觉效果无效。

编辑:

就像是:

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);
    }
}
于 2011-05-11T17:45:24.643 回答
3

如前所述,WPF 使用保留图形方法,因此您实际上在内存中创建了 100,000 个 Rectangle 对象,然后绘制所有这些对象。减速可能是由于垃圾收集和一般内存问题。

除了重写 OnRender 方法之外,您还可以查看以下几件事。

  1. 使用您熟悉的 GDI 方法在后台线程中将矩形绘制到图像,然后将结果写入 WPF WriteableBitmap

  2. 使用 D3DImage 并利用硬件加速。这需要您了解 DirectX(或 Direct2D)库。如果您对这种方法感兴趣,我建议您研究 SlimDx。

于 2011-05-11T18:00:19.177 回答
3

问题很可能不是 WPF 无法渲染 1000 个图形对象,而是您创建和添加的项目在 WPF 对象层次结构中太远了。毕竟,它确实将 GPU 用于所有图形繁琐的工作。

您应该添加尽可能接近“Visual”类的对象,一旦开始添加基于后者“UIElement”的对象,您就要求 WPF 跟踪每个对象的用户点击、悬停等,而不仅仅是绘制它.

于 2011-05-11T18:40:25.487 回答