我有一个TreeView,可以从数据绑定ObservableCollections创建所有项目。我有一个GameNode对象的层次结构,每个对象有两个ObservableCollections。一个集合具有EntityAttrib对象,另一个集合具有GameNode对象。你可以说GameNode对象代表文件夹而EntityAttrib代表文件。要在同一TreeView中显示attrib和GameNodes,我使用Multibinding。 这在启动时工作正常,但是当我在层次结构中的某处添加新的GameNode时,TreeView不会更新。我在我的转换器方法中设置了一个断点,但在添加新的GameNode时没有调用它。似乎ObservableCollection没有通知MultiBinding的变化。如果我注释掉MultiBinding并且仅绑定GameNode集合,它就会按预期工作。
XAML:
<HierarchicalDataTemplate DataType="{x:Type local:GameNode}">
<HierarchicalDataTemplate.ItemsSource>
<MultiBinding Converter="{StaticResource combineConverter}">
<Binding Path="Attributes" />
<Binding Path="ChildNodes" />
</MultiBinding>
</HierarchicalDataTemplate.ItemsSource>
<TextBlock Text="{Binding Path=Name}" ContextMenu="{StaticResource EntityCtxMenu}"/>
</HierarchicalDataTemplate>
C#:
public class GameNode
{
string mName;
public string Name { get { return mName; } set { mName = value; } }
GameNodeList mChildNodes = new GameNodeList();
public GameNodeList ChildNodes { get { return mChildNodes; } set { mChildNodes = value; } }
ObservableCollection<EntityAttrib> mAttributes = new ObservableCollection<EntityAttrib>();
public ObservableCollection<EntityAttrib> Attributes { get { return mAttributes; } set { mAttributes = value; } }
}
GameNodeList是一个子类ObservableCollection
答案 0 :(得分:1)
最好的方法(只有你的EntityAttrib和GameNode是从同一个基类继承的两个不同的类)才会实际定义两个数据模板,如下所示。
<HierarchicalDataTemplate DataType="{x:Type local:GameNode}">
<HierarchicalDataTemplate DataType="{x:Type local:EntityAttrib}">
这样更好,因为以后更容易回忆起来。考虑文件系统对象,FileInfo和DirectoryInfo类实际上都是从共享公共属性的FileSystemInfo类派生的。
你应该有一个基类,“BaseGameNode”,里面有一些东西,“GameNode”和“GameEntityAttribNode”都来自“BaseGameNode”。并且它们应该只有一个Children属性,它是BaseGameNode类型的可观察集合,但它的项目实例应该根据需要不同。
您可以定义多个模板,只要它们有区别,就会自动为节点的子节点选择类型。
您绑定的值不会刷新,因为它们不是依赖属性,也不会在更改时通知。由于multibinding根本不会检测集合更改事件,除非集合的引用/实例发生更改。当您更改集合中的项目时,属性/属性的实际实例保持不变。
绑定ItemsSource = collection时,其ItemsSource将侦听CollectionChange事件并相应地更新项目。