Focus TreeViewItem(带绑定和虚拟化)

时间:2016-06-09 10:56:11

标签: c# wpf xaml data-binding treeview

我有这个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始终为null。我曾经在某处读过ContainerFromItem不喜欢虚拟化...

有什么想法吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

最后,我解决了在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();
}