Как добавить множество (больше тысячи) объектов к WrapPanel (WPF)?

Пишу программу, которая анализирует файл и в соответствии с его собержимым рисует карту, как на рисунке:
5ca3290bd30a2588489155.png
Можете подсказать, коллеги, как это сделать быстрее всего, какие именно объекты добавлять и как?

Я попробовал два варианта: с System.Windows.Media.DrawingImage и System.Windows.Shapes.Rectangle. Но они одинаково плохи, поскольку нужно создавать их в чудовищных количествах (хотя на самом деле типов квадратиков всего несколько штук) и потом это чудовищное количество добавлять к WrapPanel. Самый медленный метод в данном случае — Map.Children.Add(image), выполняемый в цикле (сами объекты в больших количествах создаются оносительно быстро).

Может есть выход из этого положения?
  • Вопрос задан
  • 415 просмотров
Пригласить эксперта
Ответы на вопрос 1
cyber_roach
@cyber_roach
UX дизайнер INEDIapps
Во первых: не использовать wrappanel.
Для подобной цели лучше canvas, но скорее всего более производительным будет написать свою панель компоновки. тут главное правило - как можно реже перерисовывать позиции элементов.
https://docs.microsoft.com/ru-ru/dotnet/framework/...
Далее сам объект, опять же наверняка вам не нужны все фичи класса Shapes, и судя по скрину все элементы одноразмерны. производительнее будет создать новый элемент основываясь на базовом frameworkelement с заданным набором свойств (цвет из enum и размер)
Кстати элемент Border производительнее чем элемент Rectangle, не знаю с чем это связанно, но это вовсе не очевидно, основываясь на логике должно быть наоборот, но практика показывает иное. Попробуйте сами вывести N тысяч бордеров против Rectangle замерив производительность.

Если элементы не всегда выводятся полностью на экран а со скроллом, то тут сразу виртуализация (отрисовывать только то что видимо).
Далее добавление. элементов в панель.
Советую просто хакнуть систему, добавляя не по одному, а срузу сотню-другую, или если количество элементов заранее известно - сразу сформировать их все (коллекцию прибиндить) на этапе загрузки. Просто сделать их невидимыми в цвет фона, далее просто меняя состояние нужного элемента на нужный цвет по индексу во время процесса (если таковой имеется) Работа с коллекциями производительнее чем всякие For c Children.Add.
Скорее всего описанный мной вариант, значительно ускорит процесс, но пожрет уйму оперативной памяти и процессорного времени, тут решение только одно - растеризовать!
Можно залить все элементы или же часть просто текстурой (например разбить на квадраты или полоски область карты)
Алгоритм тут прост - рисуете элементы (лучше часть) - "фотографируете" - получившийся Image - вставляете на нужную область
Вообще чистый хардкор это именно формировать квадраты не элементами а группой изображений.
Это на несколько порядков снизит затраты на отрисовку, но писать такой код сможет не каждый, в особенности если квадраты не статичны (меняют состояние цвета) во время выполнения или требуется интерактив (тултип или клик по квадрату например), но всё возможно, мы даже растеризацией анимации делали, самое сложное это алгоритм корректный разработать.
Самый простой, который приходит на ум - отрисовывать всю область как текстуру, на Canvas в нужное место выводить поверх 10-100 новых элементов, после чего рстеризовать всю область с новыми элементами в общую текстуру удалив эти элементы и рисуя новую партию. В итоге вообще получится просто image который ничего не весит и не ест процессор.
Так же я бы поизучал исходные коды к примеру Telerik, у них много подобных контролов с выводом миллионов объектов. (например точки на графиках).
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы