Я работаю над подобным игре приложением, которое имеет до тысячи форм (замещающие знаки и строки), которые постоянно изменяются на уровне 60 футов в секунду. Прочитав превосходную статью о рендеринге многих движущихся форм, я реализовал это использование пользовательского потомка Холста, который переопределяет OnRender
сделать рисунок через a DrawingContext
. Производительность довольно разумна, хотя использование ЦП остается высоким.
Однако статья предлагает, чтобы самый эффективный подход для того, чтобы постоянно переместить формы использовал много из DrawingVisual
экземпляры вместо OnRender
. К сожалению, хотя это не объясняет, почему это должно быть быстрее для этого сценария.
Изменение реализации таким образом не является небольшим усилием, таким образом, я хотел бы понять причины и применимы ли они ко мне прежде, чем решить переключиться. Почему мог DrawingVisual
приблизьтесь к результату в более низком использовании ЦП, чем OnRender
подход в этом сценарии?
Я думал, что Петцольд объясняет в этом параграфе;
Класс ScatterPlotVisual работает путем создавая объект DrawingVisual для каждой точки данных. Когда свойства объекта DataPoint изменяются, классу нужно только изменить объект DrawingVisual связанный с этим DataPoint.
Что основывается на более раннем объяснении;
Всякий раз, когда свойство ItemsSource изменяется, или изменяется коллекция, или свойство объектов DataPoint в коллекции изменяется, ScatterPlotRender вызывает InvalidateVisual. Это генерирует вызов OnRender, который рисует всю диаграмму рассеяния.
Это то, о чем вы спрашиваете?
Кстати, это - довольно свежий высокопроизводительный учебник по WPF, многие десятки тысяч точек в этом графике, он также 3D-рендерится и анимирован (даже использует ввод мыши для управления некоторыми преобразованиями).
Из Pro WPF на C # 2008:
Проблема, создаваемая этими приложениями, заключается не в сложности искусства, а в огромном количестве отдельных изображений. элементы. Даже если вы замените элементы Path на более легкие объекты Geometry, накладные расходы все равно будут снижать производительность приложения . Решение WPF для такого рода ситуаций - использовать модель визуального уровня нижнего уровня . Основная идея состоит в том, что вы определяете каждый графический элемент как визуальный объект, который является чрезвычайно легким ингредиентом, имеющим меньше накладных расходов, чем объект Geometry или объект пути .
Все сводится к тому, что каждый из этих эллипсов и линий, которые вы создаете, является отдельным FrameworkElement
; это означает, что он поддерживает не только проверку попадания, но также макет, ввод, фокус, события, стили, привязку данных, ресурсы и анимацию. Это довольно тяжелый объект для того, что вы пытаетесь сделать! Объект Visual
пропускает все это и наследуется непосредственно от DependencyObject
. Он по-прежнему обеспечивает поддержку проверки попадания, преобразования координат и вычислений ограничивающего прямоугольника, но ничего другого, что поддерживает фигуры. Он намного легче и, вероятно, значительно улучшит вашу производительность.
РЕДАКТИРОВАТЬ:
Хорошо, я неправильно понял ваш вопрос в первый раз.
В случае, если вы используете OnRender
, это действительно зависит от того, как вы создаете визуальные эффекты и отображаете их.Если вы используете DrawingContext
и добавляете все визуальные элементы в один элемент, это ничем не отличается от подхода DrawingVisual
. Если бы вы создавали отдельный элемент для каждого созданного Visual
, то это было бы проблемой. Мне кажется, что вы все делаете правильно.
Все в ответах ошибались. Вопрос в том, быстрее ли рендеринг фигур непосредственно в контексте рисования, чем создание DrawingVisual. Ответ очевиден - «да». Такие функции, как DrawLine, DrawEllipse, DrawRectangle и т. Д., Не создают никаких элементов пользовательского интерфейса. DrawingVisual намного медленнее, потому что он создает элемент пользовательского интерфейса, хотя и легкий. Путаница в ответах заключается в том, что люди просто копируют / вставляют DrawingVisual лучше, чем отдельный оператор форм UIElement из MSDN.