Как я могу переопределить TreeViewItem в WPF, чтобы разрешить асинхронную загрузку дочерних элементов? - PullRequest
3 голосов
/ 16 сентября 2009

Я использую MVVM в качестве своей архитектуры WPF, и у меня WPF TreeView, реализованный в качестве отложенной загрузки (дочерние элементы не загружаются рекурсивно, пока вы не развернетесь).

Однако мне нужно реализовать асинхронную загрузку и при расширении. Есть способ сделать это? Мне нужно сохранить это на уровне управления, а не на уровне кода / приложения.

Спасибо

Ответы [ 4 ]

2 голосов
/ 16 сентября 2009

Зачем вам нужно реализовать это в самом элементе управления?

Предполагая, что это не является абсолютным требованием, я бы обработал это в свойстве, которое возвращает дочерние элементы указанного узла. Если дочерние элементы еще не заполнены, используйте фоновый поток для загрузки дочерних элементов, и, как только они будут найдены, уведомите поток пользовательского интерфейса, а затем добавьте дочерний объект в коллекцию дочерних элементов. Предполагая, что вы используете ObservableCollection (или хотя бы коллекцию, которая реализует INotifyCollectionChanged), при добавлении дочерних элементов они будут отображаться в пользовательском интерфейсе асинхронно.

0 голосов
/ 03 марта 2010

Вот как это сделать:

  1. Создать вложенное свойство типа IEnumerable
  2. В обработчике PropertyChanged для свойства приведите отправителя к TreeViewItem и проверьте свойство IsExpanded.
  3. Если IsExpanded имеет значение true, выполните Dispatcher.BeginInvoke в ApplicationPriority.ApplicationIdle с приоритетом для вашей процедуры заполнения
  4. Если IsExpanded имеет значение false, установить событие, чтобы определить, когда оно становится истинным, и в обратном вызове выполнить Dispatcher.BeginInvoke для вашей процедуры заполнения
  5. В вашей процедуре заполнения установите для ItemsSource целевого элемента управления значение присоединенного свойства
  6. Используйте стиль для установки присоединенного свойства в TreeViewItem вместо того, чтобы устанавливать его через HierarchicalDataTemplate (не указывайте ItemsSource там)

Это препятствует тому, чтобы TreeViewItem когда-либо устанавливал свой ItemsSource, пока он не будет расширен. Создание этого механизма является некоторой работой, но после его создания вы можете выполнить любую задержку загрузки TreeView, просто удалив ItemsSource из HierarchicalDataTemplate и установив его в свой ItemContainerStyle.

0 голосов
/ 03 марта 2010

Для каждого элемента пользовательского интерфейса, который требует отложенной загрузки, я использовал «Просмотр GUID».

Пояснения к примеру:

  1. В начале Control.Tag = "0000-0000 ...."
  2. Пользователь взаимодействует,
    • генерируется случайный GUID, а именно guid1
    • Control.Tag = guid1
    • создан поток, который принимает (что делать, control, guid1)
  3. между ними пользователь совершает другое взаимодействие
    • генерируется случайный GUID (на этот раз guid2)
    • Control.Tag = guid2
    • создан поток, который принимает (что делать, control, guid2)
  4. Первый поток заканчивается:
    • вызывает код в потоке пользовательского интерфейса, который получает результаты и guid, полученный до выполнения
    • вызванный код проверяет, что Control.Tag! = Guid1, делает нет изменения
  5. Второй поток заканчивается:
    • вызывает код в потоке пользовательского интерфейса, который принимает результаты и guid, полученный до выполнения
    • вызванный код видит, что Control.Tag == guid2, делает изменения
0 голосов
/ 16 сентября 2009

Если вы используете ленивую загрузку и HierarchicalDataTemplates, вы получите только те элементы, которые вы выбрали для загрузки. Имейте в виду, что TreeView необходимо загрузить на один уровень ниже того, что он отображает, чтобы определить, должна ли отображаться кнопка «Развернуть / свернуть»

...