views:

2857

answers:

3

Here is some XAML

<HierarchicalDataTemplate DataType="{x:Type data:FolderEntity}" 
  ItemsSource="{Binding Path=FolderEntities,UpdateSourceTrigger=PropertyChanged}">
  <Label Content="{Binding FolderName}"/>
</HierarchicalDataTemplate>
<TreeView/>

data:FolderEntity is a LINQ to SQL data class which implements the INotifyPropertyChanging and INotifyPropertyChanged interfaces.

My problem is that when I change the FolderEntities property the binding doesn't update. If I change the FolderName property the tree node that corresponds to that item will change, but the collection that is FolderEntities just wont.

I'm thinking WPF checks to see whether the collection reference has changed, or does the ItemsSource object have to be an ObservableCollection`1 for this to work?

Any input on the matter is much appreciated.

+2  A: 

Yes, the underlying collection (FolderEntities) will need to be an ObservableCollection<T> for the HierarchicalDataTemplate to be notified of the changes. Either that or a collection that implements INotifyCollectionChanged.

Matt Hamilton
A: 

Matt is correct. For the data binding engine to be notified of a change within a collection it need to bind to an ObservableCollection.

What you were binding to was the property and PropertyChanged (from INotifyPropertyChanged) was only being called when the property was being set e.g. FolderEntities = aNewValue; the binding engine was unaware of any changes that occurred within the collection.

Dennis Roche
I did make sure that the object sent a notification that the property FolderEntities had changed. However, it didn't work. Which surprises me as I'm telling the data binding engine that the property has changed, still no update is taking place.
John Leidegren
+2  A: 

This is how I got it to work, thanks Matt!

public abstract class ObservableHierarchy<T>
{
    public T Current { get; set; }

    public ObservableCollection<ObservableHierarchy<T>> Children { get; set; }

    public ObservableHierarchy( T current, Func<T, IEnumerable<T>> expand )
    {
        this.Current = current;
        this.Children = new ObservableCollection<ObservableHierarchy<T>>();
        foreach ( var item in expand( current ) )
        {
            Children.Add( Create( item ) );
        }
    }

    protected abstract ObservableHierarchy<T> Create( T item );
}

Then I specialize that base class to whatever data class I'm currently using.

public class ObservableFolderHierarchy:
    ObservableHierarchy<FolderEntity>
{
    public ObservableFolderHierarchy( FolderEntity root )
        : base( root, x => x.FolderEntities )
    {
    }

    protected override ObservableHierarchy<FolderEntity> Create( FolderEntity item )
    {
        return new ObservableFolderHierarchy( item );
    }
}

Slightly modified XAML and it works just great! Changes to the collection or properties of Current updates the TreeView accordingly.

<HierarchicalDataTemplate DataType="{x:Type ui:ObservableFolderHierarchy}"
 ItemsSource="{Binding Children}">
 <StackPanel Orientation="Horizontal">
  <Image Source="/UI/Resources/folder.png" Width="16" Height="16"/>
  <TextBlock Text="{Binding Current.FolderName}"/>
 </StackPanel>
</HierarchicalDataTemplate>
John Leidegren