У меня драматические c проблемы с производительностью во время реализации функции «масштабирования» для пользовательского интерфейса редактора, который я создаю.
Элементы пользовательского интерфейса в основном структурированы следующим образом:
- ScrollViewer
- Canvas («панель редактирования»)
- ItemsControl
- Canvas («item»)
- ScrollViewer
- Canvas («внутренняя панель редактирования»)
Каждый элемент ItemsControls может иметь несколько элементов (позже: меньше 100, но я тестирование только с 1-2). Каждый Canvas
, перечисленный выше, на самом деле является UserControl
с единственным элементом содержимого Canvas
.
Элементы позиционируются путем привязки свойства RenderTransform
элементов к экземпляру TranslateTransform
и размера путем привязки Width
, Height
к простым двойным свойствам.
Когда пользователь увеличивает или уменьшает масштаб (путем прослушивания события OnPreviewMouseWheel
), вычисляется новое соотношение пикселей и обновляются вышеупомянутые свойства (RenderTransform, Width, Height), в т. правильная реализация INotifyPropertyChanged
.
Я пробовал профилировать приложение с помощью инструментов VS2019 Diagnosti c, и большая часть работы, похоже, выполняется методом FrameworkElement.Arrange
. И, соответственно, если я использую профилировщик производительности, временная шкала показывает, что «Макетирование» занимает много времени.
При быстром масштабировании и с высоким коэффициентом масштабирования (т. Е. «Панель редактирования» действительно большая) приложение иногда случайным образом зависает на несколько секунд (!), Обрабатывает одно изменение масштабирования, а затем снова останавливается. Похоже на голод в UI-потоке, но я не понимаю почему. * переопределить. Если я включу это, я могу быстрее вызвать зависание, но я считаю, что это общая проблема. Кроме того, удаление элементов с вложенными ScrollViewer
s также (очевидно) снижает нагрузку на рендеринг.
Линейка, в частности, кажется дорогостоящей, хотя (согласно Diagnosti c Tools) не из-за необходимые расчеты выполнены в OnRender
, а макет - в Arrange
.
Этот ответ ({ ссылка }) помог мне изменить способ обновления значений TranslateTransform
, но заметно не улучшил производительность.
Эта ссылка интересно, но в конечном итоге не помогло мне решить мою проблему: https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/bb613542 (v = vs.100)? redirectedfrom = MSDN
После прочтения этих двух сообщений я попытался возиться с MeasureOverride
и ArrangeOverride
, но это привело к другим проблемам, и я чувствовал, что иду не в правильном направлении: WPF MeasureOverride и ArrangeOverride https://www.dotnetforall.com/understanding-measureoverride-and-arrangeoverride/
Я попытался спроектировать компоненты таким образом, чтобы обеспечить быстрый рендеринг, особенно пытаясь сделать макеты элементов управления как можно более независимыми друг от друга, но я, должно быть, делаю что-то не так. Я что-то не замечаю? Могут ли свойства типа ClipToBounds
оказать (неожиданное) влияние? ... или Opacity
настройки?
Любые идеи были бы очень признательны!
PS Я заметил, что приложение работает намного плавнее (хотя я все еще могу спровоцировать зависание / зависание), если я запускаю его с помощью профилировщика производительности или «Запуск без отладки» - не сильно ли подключение отладчика снижает производительность WPF?