Making UI Notice Change in ObservableCollection Item

I’ve been doing a lot of WPF work lately. I’m getting my head more and more around binding, especially binding to ObservableCollections. It’s interesting how the binding in XAML automagically detects additions and deletions to a collection and updates the UI appropriately. However, I ran into an issue where the update was not to the collection itself, but to item in the collection.

As an example suppose you had the ItemSource of a listbox bound to an ObervableCollection of ‘Coach’ objects.

<ListBox x:Name="lbCoaches"  
                         VerticalAlignment="Stretch" 
                         HorizontalAlignment="Stretch" 
                         DockPanel.Dock="Top"
                         ItemsSource="{Binding Path=Coaches}"
                         SelectedItem="{Binding Path=ActiveCoach}" >
      <ListBox.ItemTemplate>
      <DataTemplate>
            <StackPanel  Orientation="Horizontal">
                <TextBlock Text="{Binding Path=LastName}"></TextBlock>
                <TextBlock Text="{Binding Path=FistName}"></TextBlock>
                <TextBlock Text="{Binding Path=Age}" ></TextBlock>
            </StackPanel>
        </DataTemplate>
       </ListBox.ItemTemplate>
<ListBox>

If you add, or delete, or move a coach in the collection no problem, listbox items are updated. If you change a coaches last name, nothing. I realized that in order to get the binding to update I had to force the UI to know the ObservableCollection updated. I initially tried firing OnPropertyChanged on the collection, but that did not seem to do anything. What I realized what I needed to allow for checks to changes to the items themselves. I could have put a data trigger in place to do this, and I may yet go that route. I think for large lists this is the way to go. For my purposes, since my lists were small, I just cleared and rewrote this lists, hence forcing the UI to realize the collection had changed. Thanks to LINQ I can do this in very few lines.

    //-- coaches is observablecollection backing listbox.
     Coaches[0].LastName = "Thompson";
     var newList = Coaches.ToList();
     Coaches.Clear();
     newList.ForEach(item => Coaches.Add(item));

I think the data trigger is probably the right way to go. The above code will probably confuse people reviewing it and feels like a hack to me. Glad I thought about it, I’ll probably change it now that I was forced to think it through for this post.

Leave a Reply

Your email address will not be published. Required fields are marked *