【问题标题】:Focus TreeViewItem (with binding and virtualization)Focus TreeViewItem(带绑定和虚拟化)
【发布时间】:2016-10-09 23:45:21
【问题描述】:

我有这个 TreeView 控件:

<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 始终为空。我有时在某处读到 ContainerFromItem 不喜欢虚拟化...

有什么想法吗?

谢谢!

【问题讨论】:

  • ContainerFromItem 在项目创建之前将不起作用。尝试将 VirtualizingPanel.IsVirtualizing="False" 添加到您的树视图中。你的视图模型对吗?你实现了 INotifyPropertyChanged 了吗?
  • INotifyPropertyChanged 在 TreeItem 基类中实现。当然……删除虚拟化可以解决问题,但这就是重点……例如,在没有虚拟化的情况下向 TreeView 添加 30.000 个项目:180 秒。使用虚拟化:1 秒。

标签: c# wpf xaml data-binding treeview


【解决方案1】:

最后我解决了这个问题,在 TreeItem 基类中实现了 Focus() 方法。所以,基类看起来像这样:

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();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2019-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    • 2014-06-08
    相关资源
    最近更新 更多