2010-06-28 96 views
1

我有一个绑定到我无法控制的集合类的TreeView。这个类内部是一个对象集合,每个对象都有自己的项目集合。此层次结构固定为3深。 TreeView的子元素包含在ObservableCollection中,并相应地在TreeView中进行更新。每个对象中的集合都是不可观察的,因此每次向其中一个子对象添加对象时,我都必须手动将数据绑定到TreeView。这会导致所有展开的子项都重置为未展开状态。我试图缓存已扩展的对象,以便在重新绑定后可以重新展开。孩子们按我期望的方式工作,但是当我尝试扩展TreeView的孙子时,我得到一个空对象。如何在重新绑定后缓存TreeViewItems以重新展开?

为了得到一个TreeViewItem我使用的ItemsControl的ItemContainerGenerator属性:

TreeViewItem cfItem = treeView.ItemContainerGenerator 
    .ContainerFromItem(obj) as TreeViewItem; 
cfItem.IsExpanded = true; 

第二级藏品都有自己的父对象的引用。所以,因为我有很多这样的对象,它们被循环遍历,并且每个都使用它的父对象来查找它的父对象的TreeViewItem。他们被添加到收集的顺序保证(我认为)孩子总是在父母之后被处理。因此,我得到这个丑陋的代码行:

qualItem = (
    (TreeViewItem)treeView.ItemContainerGenerator 
     .ContainerFromItem(
      ((Child)obj).ParentObject 
     ) 
    ) 
    .ItemContainerGenerator.ContainerFromItem(obj) as TreeViewItem; 

这条线时,它试图从项目obj中的容器总是失败。它成功获取父TreeViewItem,但试图获取Child的TreeViewItem容器时,我总是收到null。该文件指出,ContainerFromItem()返回

“那 对应于给定的项目。一个System.Windows.UIElement返回 空,如果该项目不属于 项目收集,或者如果 系统。 Windows.UIElement尚未为其生成 。“

我知道第二级孩子存在父母的项目集合中。我检查了VS 2010中的调试器,并且所有的项目都在那里。我花了很长时间在Google上搜索答案,发现有人说容器项目是在后台工作线程上创建的,并且在尝试获取子项目容器时可能不会生成。我试着等待ItemContainerGenerator的Status属性等于GeneratorStatus.ContainersGenerated,但我仍然得到相同的结果。我需要以某种方式为我的二级孩子获取TreeViewItem容器,以便它们可以像第一级孩子一样重新展开。

回答

0

解决方法是在数据和TreeView之间添加另一个抽象层。顶级集合是一个ObservableCollection,它包含几个实现INotifyPropertyChanged的ViewModel,并且它们下面的树中还有ObservableCollections元素。该系统允许WPF更轻松地绑定并跟踪正在添加和删除的元素。

我的主要信息来源是这篇文章:

http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

0

“是对应于给定项目A System.Windows.UIElement。如果该项目不属于该项目集合,或如果System.Windows.UIElement尚未为它产生返回null。 “

看起来像是因为VirtualizationUIElement找不到,当你正在寻找它。如果集合不太大,请尝试关闭Virtualization

+0

的VirtualizingStackPanel.IsVirtualizing属性设置为false,什么也没做。 TreeView元素上是否有另一个IsVirtualizing属性? – 2010-06-28 19:20:20