WPF:选择超出根级别的 TreeViewItem [英] WPF: Select TreeViewItem broken past the root level

查看:31
本文介绍了WPF:选择超出根级别的 TreeViewItem的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试按 ID 选择一个 TreeViewItem,但在使其超过第一个(根)级别时遇到问题.我已经对此进行了大量阅读,并且正在使用以下方法.

I'm trying to select a TreeViewItem by ID, but having problems getting it to work past the first (root) level. I've done so much reading round on this and am using the method below.

private static bool SetSelected(ItemsControl parent, INestable itemToSelect) {
    if(parent == null || itemToSelect == null) {
        return false;
    }
    foreach(INestable item in parent.Items) {
        if(item.ID == itemToSelect.ID) { // just comparing instances failed
            TreeViewItem container = parent.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
            if(container != null) {
                container.IsSelected = true;
                container.Focus();
                return true;
            }
        }
        ItemsControl childControl = parent.ItemContainerGenerator.ContainerFromItem(item) as ItemsControl;
        if(SetSelected(childControl, itemToSelect))
            return true;
    }
    return false;
}

INestable 是基础级接口,由 IGroup 和 IAccount 实现:

INestable is the base level interface, implemented by IGroup and IAccount:

public interface INestable {
        string ID { get; set; }
    ...
}
public interface IAccount : INestable { 
    ...
}
public interface IGroup : INestable { 
    public IList<INestable> Children
    ...
}

我认为它一定与数据模板有关(也许):

I think it must have something to do with the datatemplates (perhaps):

<HierarchicalDataTemplate DataType="{x:Type loc:IGroup}" ItemsSource="{Binding Children}" x:Key="TreeViewGroupTemplate">
<HierarchicalDataTemplate DataType="{x:Type loc:IAccount}" x:Key="TreeViewAccountTemplate">

The Template selector for the treeview returns thr group template for IGroups and the account template for IAccounts:
<conv:TreeTemplateSelector x:Key="TreeTemplateSelector" AccountTemplate="{StaticResource TreeViewAccountTemplate}" GroupTemplate="{StaticResource TreeViewGroupTemplate}"/>
<TreeView ItemTemplateSelector="{StaticResource TreeTemplateSelector}">

它适用于所有顶级项目,只有低于此级别的项目,并且调试确认 parent.ItemContainerGenerator 确实包含所有级别的项目.

It works for all top level items, just nothing below that, and debugging confirms parent.ItemContainerGenerator does contain the items for all levels.

我知道有很多代码,但我正在花费数小时试图让它工作.谢谢你的帮助.:)

I know there's a lot of code but I'm burning through hours trying to get this to work. Thanks for any help. :)

推荐答案

问题是嵌套的 ItemContainerGenerators 并不是一开始就生成的,而是按需生成的.更重要的是,它们是在单独的线程中生成的,因此您必须在生成器上监听 StatusChanged 以确保它已准备就绪 =(

The problem is that the nested ItemContainerGenerators aren't generated all at the beginning, they are generated on-demand. And even more so, they are generated in a separate thread, so you have to listen to a StatusChanged on the generator to be sure it is ready =(

有些人建议使用 Dispatcher(就像在这个 Bea 的帖子).我尝试实现 Dispatcher 解决方案,但由于某种原因它不起作用......生成器仍然是空的 =(

Some people suggest to play with the Dispatcher (like in this Bea's post). I tried to implement the Dispatcher solution, but it didn't work for some reason... the generators are still empty =(

所以我结束了另一个,你特别要求树更新它的布局,这会导致扩展节点的生成.这是最后一种方法……您可能想对其进行一些测试以验证它是否适合您的需求.它可能会折叠一些在运行之前展开的节点.

So I ended up with another one, where you specifically ask the tree to update its layout, which causes the generation for the expanded nodes. Here's the final method... you might want to test it a little to verify that it suites your needs. It might collapse some nodes that were expanded before its run.

    private static bool SetSelected(TreeView treeView, ItemsControl parentControl, INestable itemToSelect)
    {
        if (parentControl == null || itemToSelect == null)
        {
            return false;
        }
        foreach (INestable item in parentControl.Items)
        {
            TreeViewItem container = parentControl.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;

            if (item.ID == itemToSelect.ID)
            { // just comparing instances failed
                    container.IsSelected = true;
                    container.Focus();
                    return true;
            }
            container.IsExpanded = true;
            treeView.UpdateLayout();
            WaitForPriority(DispatcherPriority.Background);
            if (SetSelected(treeView, container, itemToSelect))
                return true;
            else
                container.IsExpanded = false;
        }
        return false;
    }

这篇关于WPF:选择超出根级别的 TreeViewItem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆