Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

NotifyParentObservableCollection (Part 1) monitors changes of its children properties

0.00/5 (No votes)
23 Jan 2011 9  
ObservableCollection attaches to the PropertyChanged events of its children and raises the ChildPropertyChanged event accordingly. Very useful when you need to update / select / arrange / move items.

Table of Contents

Introduction

Some of the most common tasks in GUI programming are to select multiple items from the list, to modify properties of multiple items, to rearrange items in the list, or to copy / move items from one list to another.

I assume that you are using WPF and MVVM pattern.

Let's consider the following simple example. You want to switch on / off individual bits of the Hex variable, like this:

binary.JPG

You create properties on your ViewModel holding list(s) or collection(s) of items, and bind them to some ItemsControl(s) on your view. You make an ItemTemplate containing CheckBoxes, and bind them to properties of your items. Now what? How do you implement the needed functionality?

You have a few alternatives:

  • Make view model class(es) for your items and put all the logic there, so every time the Item.IsSelected property is changed, you update the Hex variable. Oops, the Hex variable belongs to the parent VM, so your items will have to have a member variable holding the parent VM or a delegate callback.
  • Make dumb items to hold data, make a bunch of converters, and implement logic in those converters / XAML, like so;
  • TextBox.Text = "{Binding CheckBox.IsChecked, Converter=....}"

    Of course, you will need a pretty complicated FlagConverter which can combine multiple flag values (I have a bunch of those in my WPF library).

  • Don't re-invent the wheel, and use the utility classes that I created to simplify things. With those utility classes, any task of updating / selecting / arranging / moving items is a snap.

Example

The XAML is simplicity itself:

<ListBox ItemsSource="{Binding Selectors}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox IsChecked="{Binding IsSelected}" 
                      Content="{Binding Caption}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

The ViewModel cannot be simpler:

private NotifyParentObservableCollection<LookupItem> _selectors;
public NotifyParentObservableCollection<LookupItem> Selectors
{
    get { return _selectors; }
    private set
    {
        if (_selectors != null)
        {
            _selectors.ChildPropertyChanged -= OnSelectorsChildPropertyChanged;
        }
        _selectors = value;
        if (_selectors != null)
        {
            _selectors.ChildPropertyChanged += OnSelectorsChildPropertyChanged;
        }
        OnPropertyChanged("Selectors");
    }
}

private void OnSelectorsChildPropertyChanged(object sender, 
                                             PropertyChangedEventArgs e)
{
    var item = sender as LookupItem;
    if (e.PropertyName == "IsSelected")
    {
        if (item.IsSelected)
        {
            Hex |= (int) item.Value;
        }
        else
        {
            Hex &= ~(int) item.Value;
        }
    }
}

Selectors = new NotifyParentObservableCollection<LookupItem>
{
    new LookupItem { Value = 1, Caption = "0x00000001" },
    new LookupItem { Value = 2, Caption = "0x00000010" },
    new LookupItem { Value = 4, Caption = "0x00000100" },
    new LookupItem { Value = 8, Caption = "0x00001000" },
};

Voila, we are done with our task. Can you beat the simplicity?

NotifyParentObsevableCollection and LookupItem

public class LookupItem : INotifyPropertyChanged

LookupItem is a utility class used as a generic ViewModel for an item when you need to update / select / arrange / move those items.

LookupItem has a bunch of most useful for those scenarios properties, and it implements the INotifyPropertyChanged interface to notify its parent NotifyParentObservableCollection<T> when any of its properties change. If you need more properties, inherit from it and add whatever you need.

public class NotifyParentObservableCollection<T> : ObservableCollection<T>

NotifyParentObservableCollection<T> attaches to the PropertyChanged events of its children and raises the ChildPropertyChanged event accordingly.

NotifyParentObservableCollection<T> inherits from ObservableCollection<T>, and overrides OnCollectionChanged() and ClearItems() to attach / detach handlers to children.

That's it. Again, can you beat the simplicity?

When I write code, my goal is to eliminate as much lines of code as possible, but no more.

My motto: The less lines of code, the less potential errors.

Caution

Since NotifyParentObservableCollection<T> strongly attaches to the PropertyChanged events of its children, you have to Clear() the collection after you are done using it to eliminate potential memory leaks.

Of course, if the parent collection has the same life span as its children, you can safely ignore this advice, but if children can outlive the collection, don't forget to call Clear().

Revision History

  • January 20, 2011 - Created the article.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here