эквивалентные CreateGraphics в wpf

Итак, я использовал winForms .CreateGraphics для рисования различных вещей, от линий до коробок до изображений. Он был очень резким и отзывчивым.

Я пытаюсь изучить WPF в C#

я обнаружил, что WPF позволяет мне "добавлять" объекты прямоугольника на холст, который будет отображать их правильно. Тем не менее, я рисую сотни тысяч прямоугольников время от времени, и скорость рисования может стать чрезвычайно медленной, а пользовательский интерфейс становится менее быстрым, когда я перемещаю даже 1 из прямоугольники.

рисование непосредственно на элемент в winForms было не очень быстрым, но оно было последовательным, независимо от того, сколько я рисовал.

есть ли аналогичное решение для этого в WPF?

Я попытался добавить linq в System.Drawing, что дало мне Graphics объект, но ни один из элементов wpf, которые я пробовал, не имеет .CreateGraphics() метод.

4 ответов


вам нужно будет создать элемент управления, который переопределяет метод 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);
    }
}

WPF использует другую модель для графических манипуляций, чем WinForms.

с помощью WinForms вы можете напрямую редактировать пиксели на экране. Концепция вашего прямоугольника теряется после рисования пикселей. Рисование пикселей-очень быстрая операция.

с WPF вы не контролируете пиксели на экране. Параметр DirectDraw. DirectDraw-это векторный композиционный движок. Вы не рисуете пиксели. Вы определяете векторные фигуры (или визуальные элементы). Концепция фигура или прямоугольник сохраняется даже после отображения изображения на экране. Когда вы добавляете новый прямоугольник, который перекрывает другие, все остальные прямоугольники необходимо перерисовать. Это, вероятно, где ваша производительность замедляется. Этого не происходит при использовании WinForms.

вы можете немного повысить производительность WPF, переопределив OnRender. Вы можете вырезать накладные расходы объекта Rectangle и напрямую предоставить визуальные эффекты. Однако вы все еще не рисуете пиксели к экрану. Вы определяете фигуры, которые DirectDraw использует для визуализации изображения. В этом отношении название OnRender может быть немного вводящим в заблуждение.

Я уверен, что вы можете найти много трюков для повышения производительности вашего приложения в WPF. Есть способы все еще рисовать пиксели - но это своего рода победа над точкой WPF.

Что вы делаете, что требует тысяч прямоугольников?


Как было сказано, WPF использует сохраненную графическую методологию, поэтому вы фактически создаете 100 000 объектов прямоугольника в памяти, а затем рисуете их все. Замедление, вероятно, из-за сбора мусора и общих проблем с памятью.

помимо переопределения метода OnRender, вот несколько вещей,которые вы могли бы изучить.

  1. рисование прямоугольников на изображение в фоновом потоке с помощью методов GDI, знакомых вам, а затем напишите результат для WPF WriteableBitmap

  2. используйте D3DImage и воспользуйтесь аппаратным ускорением. Для этого необходимо знать библиотеки DirectX (или Direct2D). Если вас интересует этот подход, я бы предложил изучить SlimDx.


проблема скорее всего не в том, что WPF не может отображать 1000 графических объектов, а в том, что создание и добавление элементов слишком далеко от иерархии объектов WPF. В конце концов, он использует GPU для всей графической работы.

вы должны добавить объекты как можно ближе к" визуальному " классу, как только вы начнете добавлять объекты на основе последнего "UIElement", вы просите WPF отслеживать пользовательские клики, зависания и так далее для каждого объекта, а не просто рисовать его.