wpf TreeViewItem BringIntoView не всегда работает - PullRequest
2 голосов
/ 25 февраля 2011

В моем приложении MVVM у меня есть древовидная структура, которая должна отображать древовидную структуру при выборе Древовидное представление представляет записи в базе данных. Каждый элемент древовидной структуры загружает своих дочерних элементов по требованию, расширяя элемент при его выборе.

Стиль дерева выглядит так:

  <TreeView.ItemContainerStyle>
    <Style TargetType="{x:Type TreeViewItem}">
      <Setter Property="OverridesDefaultStyle" Value="True"/>
      ...
      <EventSetter Event="Selected" Handler="OnTreeViewItemSelected"/>

Обработчик определяется следующим образом:

private void OnTreeViewItemSelected(object sender, RoutedEventArgs e)
{
  if (!Object.ReferenceEquals(sender, e.OriginalSource))
  {
    return;
  }
  TreeViewItem item = e.OriginalSource as TreeViewItem;
  if (item != null)
  {        
    EventHandler eventHandler = null;
    eventHandler = new EventHandler(delegate
    {
      treeData.LayoutUpdated -= eventHandler;
      item.BringIntoView();
    });
    treeData.LayoutUpdated += eventHandler;
  }
} 

Это прекрасно работает для уже загруженных предметов.

[Редактировать: фактически родительский элемент выбранного элемента должен быть расширен, а не только загружен]

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

Проблема с элементами, которые еще не загружены. В этих случаях мой код получает записи предков искомого элемента, перебирает их, расширяя элементы по мере их прохождения (и, следовательно, загружая дочерние элементы), пока не достигнет искомого элемента. Это выбрано успешно, НО не отображается.

Кто-нибудь знает, как решить эту проблему?

[ОБНОВЛЕНО] В TreeViewItemViewModel:

public bool IsSelected
{
  get { return _isSelected; }
  set
  {        
    if (value != _isSelected)
    {          
      _isSelected = value;

      if (value == true)          
        IsExpanded = value;          

      this.OnPropertyChanged("IsSelected");
    }
  }
}

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

    _isExpanded = value;
    this.OnPropertyChanged("IsExpanded");

    if (_isExpanded && 
        _parent != null &&
        _parent.IsExpanded == false)
      _parent.IsExpanded = true;

    LoadChildren();
  }
}

Метод LoadChildren () обрабатывает, требует ли дочерняя загрузка загрузки или нет, используя флаг.

ItemContainerStyle

Setter Property = "IsExpanded" Value = "{Binding IsExpanded, Mode = TwoWay}" Setter Property = "IsSelected" Value = "{Binding IsSelected, Mode = TwoWay}"

Ответы [ 2 ]

3 голосов
/ 26 февраля 2011

это может решить вашу проблему

и основывается на этой статье об использовании MVVM для TreeView

EDIT: также есть вероятность, что ваши древовидные контейнеры еще не созданы. тогда вы должны возиться с TreeViews ItemContainerGenerator

0 голосов
/ 01 марта 2011

Хорошо, так что я, кажется, решил это «случайно».

Если я запускаю поиск в фоновом процессе, выбранный он отображается в виде

public void Search()
{
  ImplementSearch();

  _workinghelper = new WorkingHelper();
  SearchWorkingViewModel searchvm = new SearchWorkingViewModel(_workinghelper.WorkingWindow);
  VisualUtils.FadeTreeViewItemViewModel(1.0, 0.2, 0, 100);
  _workinghelper.MakeWorking(searchvm);

  VisualUtils.FadeTreeViewItemViewModel(0.2, 1.0, 0, 001);
}

public bool CanSearch
{
  get { return _searchlogic.SearchTypeIsValid(_searchterm); }
}

void ImplementSearch()
{      
  BackgroundTaskManager.RunBackgroundTask(
    () =>
    {
      bool run_success = _searchlogic.PerformSearch(_searchterm);
      Thread.Sleep(500);
      return run_success;
    },
    (run_success) =>
    {
      if (run_success == false)
        ApplicationSetup.DisableApp((MainWindow)App.Current.MainWindow, "The search function has caused an unexpected internal error. Please contact an administrator for help.");

      if (_workinghelper != null)
        _workinghelper.DisposeWorkingWindow();
    });      
}

Однако, если я просто побегу bool run_success = _searchlogic.PerformSearch (_searchterm); в ImplementSearch () элемент НЕ отображается.

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