[WPF] Повторно не выделяется элемент в TreeView
От: Аноним  
Дата: 10.08.10 19:33
Оценка:
Добрый день.
На форме есть такое:

<TreeView>
 <TreeView.Resources>
    <Style x:Key="TreeViewItem_NoExpanded" TargetType="TreeViewItem">
       <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
    </Style>
 </TreeView.Resources>
  <TreeViewItem Header="Root" IsExpanded="True" 
                ItemsSource="{Binding Path=xxx, ElementName=window1}"/>
</TreeView>


соответсвенно xxx — это ObservableCollection, у элементов которой есть свойство IsSelected — если true, то элемент выделяется в дереве, если — false — снимается выделение.
Так вот после "выделения" объекта мышкой, последующего программного снятия выделения — SelectedValue.IsSelected = false и последующего выделения этого-же объекта мышкой — он не выделяется..., если кликнуть по другому элементу, то он выделется без проблем. Такое ощущение, что первый элемент осьается выделенным после IsSelected = false. Никто с таким не сталкивался?
Re: [WPF] Повторно не выделяется элемент в TreeView
От: MxMsk Португалия  
Дата: 10.08.10 20:47
Оценка:
Здравствуйте, Аноним, Вы писали:

А>соответсвенно xxx — это ObservableCollection, у элементов которой есть свойство IsSelected — если true, то элемент выделяется в дереве, если — false — снимается выделение.

А>Так вот после "выделения" объекта мышкой, последующего программного снятия выделения — SelectedValue.IsSelected = false и последующего выделения этого-же объекта мышкой — он не выделяется..., если кликнуть по другому элементу, то он выделется без проблем. Такое ощущение, что первый элемент осьается выделенным после IsSelected = false. Никто с таким не сталкивался?
Сталкивался. Проблема в том, что выделение элемента в TreeView по нажатию мыши делается через фокусировку. Происходит следующее. Мышь нажимается на TreeViewItem, зовется метод Focus, в результате которого зовется метод GotFocus, который перекрыт в TreeViewItem и вызывает Select, выделяя элемент в дереве. Далее IsSelected делается false, и выделение хоть и уходит, но фокусировка остается. Следом мышь снова нажимается, и снова зовется Focus, однако на этот раз элемент уже сфокусирован прошлым нажатием мыши. Следовательно изменения фокуса не происходит, а значит не будет вызова GotFocus, а следовательно не будет вызова Select. Как это побороть? — добиться ухода фокуса с TreeViewItem. Можно написать attached behavior, который при изменении IsSelected в false, будет снимать фокус с TreeViewItem. Вопрос в том, на кого этот фокус перекинуть. В последнем WPF появился метод Keyboard.ClearFocus, возможно он подойдет. Что касается моего случая, то я в итоге просто забил на эту проблему, т.к. красиво решить ее не выходит, а описанная последовательность действий не такая уж частая, мне кажется.
Re[2]: [WPF] Повторно не выделяется элемент в TreeView
От: Аноним  
Дата: 27.01.11 08:04
Оценка:
Здравствуйте, MxMsk,

В WPF 4 проблема решается двумя вызовами после IsSelected = false:

    private void OnCalcsTreePreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
      TreeView Source = sender as TreeView;
      if (e.OriginalSource.GetType().Name == "ScrollViewer")
      {
        if (Source.SelectedItem != null)
        {
          TreeViewItem Container = Source.GetContainerByObject(Source.SelectedItem);
          if (Container != null)
          {
            Container.IsSelected = false;
            FocusManager.SetFocusedElement(Source, e.OriginalSource as IInputElement);
            Keyboard.Focus(Source );
          }
        }
      }
    }

  public static class TreeViewExtensions
  {
    public static TreeViewItem GetContainerByObject(this TreeView treeView, Object reference)
    {
      return GetContainerByObjectInternal(treeView, reference);
    }

    private static TreeViewItem GetContainerByObjectInternal(ItemsControl itemsControl, Object reference)
    {
      ValidateItemsControl(itemsControl);
      if (itemsControl.Items.Contains(reference))
        return itemsControl.ItemContainerGenerator.ContainerFromItem(reference) as TreeViewItem;
      else
      {
        foreach (Object item in itemsControl.Items)
        {
          TreeViewItem CurrentItem = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
          if (CurrentItem != null)
          {
            TreeViewItem FindedContainer = GetContainerByObjectInternal(CurrentItem, reference);
            if (FindedContainer != null)
              return FindedContainer;
          }
        }
      }

      return null;
    }

    private static void ValidateItemsControl(ItemsControl itemsControl)
    {
      Debug.Assert(itemsControl is TreeViewItem || itemsControl is TreeView);
    }
  }
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.