2016-06-09 1 views
0

У меня есть этот контроль TreeView:Фокус TreeViewItem (с обязательным и виртуализации)

<TreeView x:Name="treeView" HorizontalAlignment="Left" Margin="0" Width="300" ItemsSource="{Binding TvMview.FirstNodes}" 
       VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling"> 
     <TreeView.ItemTemplate> 
      <HierarchicalDataTemplate ItemsSource="{Binding SecondNodes}"> 
       <HierarchicalDataTemplate.ItemTemplate> 
        <HierarchicalDataTemplate ItemsSource="{Binding ThirdNodes}"> 
         <StackPanel Orientation="Horizontal"> 
          <TextBlock Text="{Binding HeaderText}" Background="Red"/> 
         </StackPanel> 
        </HierarchicalDataTemplate> 
       </HierarchicalDataTemplate.ItemTemplate> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text=">>> " Background="Green"/> 
        <TextBlock Text="{Binding HeaderText}" Background="blue"/> 
       </StackPanel> 
      </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
     <TreeView.ItemContainerStyle> 
      <Style TargetType="TreeViewItem"> 
       <Setter Property="IsSelected" Value="{Binding IsSelected}" /> 
       <Setter Property="IsExpanded" Value="{Binding IsExpanded}" /> 
      </Style> 
     </TreeView.ItemContainerStyle> 
    </TreeView> 

привязываться к:

public class ModelView 
{ 
    public TreeViewModelView TvMview { get; set; } = new TreeViewModelView(); 
} 

public class TreeViewModelView 
{ 
    public ObservableCollection<FirstNode> FirstNodes { get; set; } = new ObservableCollection<FirstNode>(); 
} 

public class FirstNode : TreeItem 
{ 
    public ObservableCollection<SecondNode> SecondNodes { get; set; } = new ObservableCollection<SecondNode>(); 
    public string HeaderText { get; set; } 
} 

public class SecondNode : TreeItem 
{ 
    public ObservableCollection<ThirdNode> ThirdNodes { get; set; } = new ObservableCollection<ThirdNode>(); 
    public string HeaderText { get; set; } 
} 

public class ThirdNode 
{ 
    public string HeaderText { get; set; } 
} 

public class TreeItem 
{ 
    public bool IsExpanded { get; set; } 
    public bool IsSelected { get; set; } 
} 

И все работает, как ожидалось. Но ... Я хочу осуществить знакомство:

foreach (var firstNode in Mview.TvMview.FirstNodes) 
     { 
      if (firstNode.HeaderText.Contains(textBox.Text)) 
      { 
       firstNode.IsExpanded = true; 
       firstNode.IsSelected = true; 
       TreeViewItem tvItem = (TreeViewItem)treeView.ItemContainerGenerator.ContainerFromItem(firstNode); 
       tvItem?.Focus(); 
       return; 
      } 
     } 

Правый узел расширен, но tvItem всегда имеет значение null. Я где-то где-то читал, что ContainerFromItem не любит виртуализацию ...

Любая идея?

Спасибо!

+0

ContainerFromItem не будет работать, пока деталь не была создана. Попробуйте добавить VirtualizationPanel.IsVirtualizing = "False" к вашему древовидной структуре. Правильны ли ваши модели? Вы реализовали INotifyPropertyChanged? – user2880486

+0

INotifyPropertyChanged реализован в базовом классе TreeItem. И конечно ... удаление виртуализации устраняет проблему, но, вот и все дело ... Например, добавление 30.000 элементов в TreeView без вирутализации: 180 секунд. с виртуализацией: 1 сек. –

ответ

0

Наконец, я решил эту проблему реализовать метод Focus() в базовом классе TreeItem. Таким образом, базовый класс выглядеть следующим образом:

public class TreeItem : INotifyPropertyChanged 
{ 
    private bool _IsExpanded; 
    public bool IsExpanded 
    { 
     get { return _IsExpanded; } 
     set { _IsExpanded = value; OnPropertyChanged("IsExpanded"); } 
    } 

    private bool _IsSelected; 
    public bool IsSelected 
    { 
     get { return _IsSelected; } 
     set { _IsSelected = value; OnPropertyChanged("IsSelected"); } 
    }   

    public void Focus(TreeView tView) 
    { 
     TreeViewItem tvItem = (TreeViewItem)tView.ItemContainerGenerator.ContainerFromItem(this); 
     tvItem?.Focus(); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void OnPropertyChanged(string property) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
    } 
} 

А вы можете назвать это так:

if (firstNode.HeaderText.Contains(textBox.Text)) 
{ 
    firstNode.IsExpanded = true; 
    firstNode.IsSelected = true; 
    firstMatch.Focus(); 
} 
Смежные вопросы