Я работал над высокопроизводительным древовидным представлением, которое на самом деле основано на ListBox
. Чтобы достичь этого, мы сначала начнем с иерархической модели, в которой каждый элемент реализует интерфейс IParent
, который предоставляет перечисляемое свойство Children
.
Затем мы «сплющиваем» эту иерархию в ViewModel на основе списка, добавляя свойство «глубина» к каждому элементу. Затем мы используем этот список как ItemsSource
из ListBox
, используя новое свойство глубины для отступа ContentPresenter
в нашем пользовательском шаблоне ListBoxItem
. Все это работает как чемпион и позволяет нам отображать несколько тысяч узлов, что-то нормальное TreeView
захлебнется. Это происходит потому, что, опять же, это просто список, и ListBox
легко виртуализирует свои контейнеры по умолчанию, тогда как TreeView
общеизвестно борется с виртуализацией.
Рассмотрим этот пример иерархии:
Parent1
Parent2
Child2a
Grandchild2a1
Grandchild2a2
Child2b
Parent3
Child3a
После сглаживания становится так ...
Parent1, Level 0
Parent2, Level 0
Child2a, Level 1
Grandchild2a1, Level 2
Grandchild2a2, Level 2
Child2b, Level 1
Parent3, Level 0
Child3a, Level 1
В настоящее время я делаю все это выравнивание, внешнее по отношению к элементу управления, но мне пришло в голову, что если я вместо этого создаю HierarchicalItemsControl
, он может сделать это выравнивание внутренне, то есть я мог бы использовать его для любой данные иерархической модели, которые реализовали IParent
(или даже если это не так, через делегат GetChildren.)
Проблема, с которой я сталкиваюсь при таком подходе, заключается в обычном ItemsControl
, существует взаимно-однозначное отношение между элементами в свойствах Items
/ ItemsSource
и созданными контейнерами, которые расположены на ItemsPanel
. В этом случае существует отношение один ко многим.
Просто, я думал ... добавьте HierarchicalItems
/ HierarchicalItemsSource
свойства, а затем установите обычные свойства Items
/ ItemsSource
после выравнивания. Это поддерживало бы отношения один-к-одному.
Проблема в том, что свойства Items
/ ItemsSource
доступны для чтения / записи, что означает, что люди могут напрямую ими манипулировать, и это нарушит внутреннюю логику моего контроля.
Я начинаю думать, что не могу использовать подкласс ItemsControl
, и вместо этого мне придется создавать собственный базовый класс HierarchicalItemsControl
, переопределяя большинство внутренних элементов ItemsControl
вручную, но я надеюсь, что есть по-другому.
В итоге ...
Основная проблема, которую я пытаюсь решить, - это способ для этого специализированного HierarchicalItemsControl
создать несколько контейнеров для каждого элемента в отличие от обычного ItemsControl
.
.
Внутренне это в конечном итоге будет один к одному со сглаженным списком, но внешне я не хочу, чтобы люди могли манипулировать этим сглаженным списком (то есть я хотел заблокировать Items
/ ItemsSource
только для чтения, но я не думаю, что вы можете сделать это, поскольку они зарегистрированы DependencyProperties
, а не простые свойства CLR и AFAIK, вы не можете изменить доступность зарегистрированного DependencyProperty
.)