WPF MVVM Treeview асинхронная загрузка с задачами - PullRequest
0 голосов
/ 10 марта 2011

У меня есть приложение WPF, использующее MVVM, которое использует TreeViewItemViewModels для упрощения работы с древовидной структурой, как продемонстрировал Джош Смит http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx

Мое древовидное представление представляет записи в реляционной базе данных, и каждый узел имеет своих дочерних элементов, загружаемых по требованию. Чтобы улучшить отзывчивость пользовательского интерфейса, я пытался загрузить данные асинхронно, используя Задачи в .net 4.0, но изо всех сил стараюсь реализовать это удовлетворительно.

Свойство treeviewitemviewmodel IsExpanded выглядит так:

public bool IsExpanded
{
  get { return _isExpanded; }
  set
  {        
    if (_isExpanded == value)
      return;

    if (!_isSelected)       
      IsSelected = true;

    _isExpanded = value;

    if (_isExpanded &&
        _parent != null &&
        _parent.GetType() != typeof(FirstGenerationViewModel))
      _parent.IsExpanded = true;

    ApplicationSetup.Messenger.NotifyColleagues(ApplicationSetup.MSG_WORKING, true);

    Task task = Task.Factory.StartNew(() =>
    {
      LoadChildren();
    })
    .ContinueWith((t) => 
      {
        this.OnPropertyChanged("IsExpanded");
        ApplicationSetup.Messenger.NotifyColleagues(ApplicationSetup.MSG_WORKING, false);            
      }, ApplicationSetup.UIScheduler);        
  }
}

Если я выбираю элементы вручную, раскрываю и сворачиваю их, все работает должным образом - отображается рабочая анимация, пока выполняется LoadChildren (), а затем элементы расширяются, когда вызывается OnPropertyChanged и анимация закрывается.

Однако я пытаюсь реализовать функцию поиска. Если запись уже загружена, я просто перебираю древовидное представление, пока оно не будет найдено, и затем выбираю его. Однако, если он не загружен, процесс должен выполнить поиск в базе данных, а затем отобразить ее. Поскольку записи загружаются по требованию, процесс получает искомый элемент и его предков из БД и пытается развернуть каждого предка по очереди, затем, наконец, выбирает искомый элемент:

      foreach (var item in ancestors.Keys)
      {            
        TreeViewItemViewModel tv = _fgvm.recordsViewHelper.GetTreeViewItem(new ItemArgs 
                                                                            { 
                                                                              TargetTableName = item, 
                                                                              TargetPk = ancandtarget[item]
                                                                            });

        tv.IsExpanded = true;            
      }

Если искомый элемент находится высоко в иерархии, это работает. Тем не менее, когда запись вложена в несколько элементов, tv становится нулевым. Я думаю, это потому, что элемент не был загружен до того, как _fgvm.recordsViewHelper.GetTreeViewItem пытается найти его в древовидном представлении.

Как я могу это сделать? Я пытался использовать Wait (), но кажется, что пользователь зависает.

1 Ответ

0 голосов
/ 08 марта 2012

Решил это сам. На самом деле очевидно. Теперь я использую метод-оболочку для расширения предков в цикле foreach, который возвращает задачу, используемую свойством IsExpanded. Эта задача может затем вызывать функцию Wait (), которая гарантирует, что родители следующего предка будут полностью загружены перед продолжением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...