WPF TreeView bound to ObservableCollection not upd

2019-02-06 17:52发布

问题:

Sorry - my question is almost identical to this one but since it didn't receive a viable answer, I am hoping that someone else has some fresh ideas.

I have a WPF TreeView that is bound to a hierarchy of a single type:

public class Entity
{
    public string Title { get; set; }
    public ObservableCollection<Entity> Children { get; set; }
}

The Entity class implements INotifyPropertyChanged, but I have omitted this code for clarity.

The TreeView is bound to an ObservableCollection<Entity> and each Entity instance exposes a set of contained Entity instances via its Children property:

<TreeView ItemsSource="{Binding Path=Entities}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:Entity}" ItemsSource="{Binding Path=Children}">
           <TextBlock Text="{Binding Path=Title}" />
        </HierarchicalDataTemplate>
   </TreeView.Resources>
</TreeView>

Initially the TreeView binds as expected and correctly displays a multi-level hierarchy. Also, when the membership of one of the Children collections is programmatically modified, the changes are correctly reflected in the TreeView.

However, changes to the membership of the root member level ObservableCollection<Entity> are not reflected in the TreeView.

Any suggestions would be appreciated.

Thanks, Tim

回答1:

My initial guess is that you have something like the following for the root node:

public ObservableCollection<Entity> Entities
{
    get;
    set;
}

Then, instead of doing something [good] like the following:

Entities.Clear();
foreach (var item in someSetOfItems)
    Entities.Add(item);

You are doing something [bad] like this:

Entities = new ObservableCollection<Entity>(someSetOfItems);

You should be able to track down the issue by making the backing field of the Entities property readonly:

private readonly ObservableCollection<Entity> _entities
    = new ObservableCollection<Entity>();

public ObservableCollection<Entity> Entities
{
    get
    {
        return _entities;
    }
}


回答2:

Further explanation, long time for answer to come, but I believe that if you do the binding in XAML, and then in code assign a new object to the property you break the binding, so you would have to redo the binding in code for it to work. Hence the solution with the readonly backing field. If doing like that you will not be able to assign a new ObservableCollection and you won't break the binding by assigning a new object to the backing field.