views:

3522

answers:

4

Hello,

does anyone know why this code doesn't work:

public class CollectionViewModel : ViewModelBase {  
    public ObservableCollection<EntityViewModel> ContentList
    {
        get { return _contentList; }
        set 
        { 
            _contentList = value; 
            RaisePropertyChanged("ContentList"); 
            //I want to be notified here when something changes..?
            //debugger doesn't stop here when IsRowChecked is toggled
        }
     }
}

public class EntityViewModel : ViewModelBase
{

    private bool _isRowChecked;

    public bool IsRowChecked
    {
        get { return _isRowChecked; }
        set { _isRowChecked = value; RaisePropertyChanged("IsRowChecked"); }
    }
}

Thanks a lot!

Cheers

PS: ViewModelBase containts everything for RaisePropertyChanged etc. and it's working for everything else except this problem..

+3  A: 

The ContentList's Set method will not get called when you change a value inside the collection, instead you should be looking out for the CollectionChanged event firing.

public class CollectionViewModel : ViewModelBase
{          
    public ObservableCollection<EntityViewModel> ContentList
    {
        get { return _contentList; }
    }

    public CollectionViewModel()
    {
         _contentList = new ObservableCollection<EntityViewModel>();
         _contentList.CollectionChanged += ContentCollectionChanged;
    }

    public void ContentCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        //This will get called when the collection is changed
    }
}


EDIT

Okay, that's twice today I've been bitten by the MSDN documentation being wrong. In the link I gave you it says:

Occurs when an item is added, removed, changed, moved, or the entire list is refreshed.

But it actually doesn't fire when an item is changed. I guess you'll need a more bruteforce method then:

public class CollectionViewModel : ViewModelBase
{          
    public ObservableCollection<EntityViewModel> ContentList
    {
        get { return _contentList; }
    }

    public CollectionViewModel()
    {
         _contentList = new ObservableCollection<EntityViewModel>();
         _contentList.CollectionChanged += ContentCollectionChanged;
    }

    public void ContentCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            foreach(EntityViewModel item in e.NewItems)
            {
                //Removed items
                item.PropertyChanged -= EntityViewModelPropertyChanged;
            }
        }
        else if (e.Action = NotifyCollectionChangedAction.Add)
        {
            foreach(EntityViewModel item in e.NewItems)
            {
                //Added items
                item.PropertyChanged += EntityViewModelPropertyChanged;
            }     
        }       
    }

    public void EntityViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        //This will get called when the property of an object inside the collection changes
    }
}

If you are going to need this a lot you may want to subclass your own ObservableCollection that triggers the CollectionChanged event when a member triggers its PropertyChanged event automatically (like it says it should in the documentation...)

Martin Harris
I was looking for this for so long! Thanks a lot!
Joseph Melettukunnel
Sorry Harris, but what Event do I have to fire in EntityViewModel so that ContentCollectionChanged gets called?
Joseph Melettukunnel
Genius, works like a charm!
Joseph Melettukunnel
note that if you don't want to implement the event management yourself, you can use a BindingList<EntityViewModel> in place of ObservableCollection<EntityViewModel>. It will then automatically forward EntityViewModel.PropertyChanged events as ListChanged events where ListChangedType == ItemChanged.
mjeanes
A: 

No this will never work because collection does not refresh or fires any event at all if one of the item of collection fires any event you will have to pass a reference of your collection inside your item in order to fire any event.

You will have to choose some different approach.

Akash Kava
A: 

ObservableCollection will not propagate individual item changes as CollectionChanged events. You will either need to subscribe to each event and forward it manually, or you can check out the BindingList[T] class, which will do this for you.

mjeanes
A: 

There is a good article (samples in VB) on ObservableCollections in the msdn magazine Advanced Basics - The ObservableCollection Class that explains the problem in more detail.