ObservableCollection не обновляет Multibinding в C # WPF - PullRequest
1 голос
/ 18 сентября 2009

У меня есть TreeView, который создает все свои элементы из привязанной к данным ObservableCollections. У меня есть иерархия объектов GameNode, у каждого объекта есть две ObservableCollections. В одной коллекции есть объекты EntityAttrib, а в другой - объекты GameNode. Можно сказать, что объект GameNode представляет папки, а EntityAttrib представляет файлы. Чтобы отобразить attrib и GameNodes в одном TreeView, я использую 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

1 Ответ

1 голос
/ 18 сентября 2009

Лучший способ сделать это (только если ваши EntityAttrib и GameNode - это два разных класса, унаследованных от одного базового класса) - это на самом деле определить два шаблона данных, как показано ниже.

<HierarchicalDataTemplate DataType="{x:Type local:GameNode}">        

<HierarchicalDataTemplate DataType="{x:Type local:EntityAttrib}">        

Это лучше, потому что потом легче вспомнить. Рассмотрим объекты файловой системы. Классы FileInfo и DirectoryInfo фактически являются производными от класса FileSystemInfo, который имеет общее свойство.

У вас должен быть базовый класс "BaseGameNode", в нем должно быть что-то, "GameNode" и "GameEntityAttribNode", оба производные от "BaseGameNode". И у них должно быть только одно свойство Children, которое является наблюдаемой коллекцией типа BaseGameNode, но его экземпляр элемента должен отличаться при необходимости.

Вы можете определить несколько шаблонов при условии, что им есть, что различать, тип будет автоматически выбран для дочерних элементов узла.

Значение, которое вы связали, не будет обновляться, поскольку они не являются свойством зависимости и не уведомляют об изменении. Так как мультисвязывание вообще не обнаружит событие изменения коллекции, пока не изменится ссылка / экземпляр коллекции. Когда вы изменяете элемент в коллекции, ваш фактический экземпляр атрибутов / свойств остается прежним.

Когда вы связываете ItemsSource = collection, это ItemsSource, который будет прослушивать событие CollectionChange и обновлять элементы соответствующим образом.

...