Skip to content

Instantly share code, notes, and snippets.

@itajaja
Created November 17, 2013 00:04
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save itajaja/7507120 to your computer and use it in GitHub Desktop.
Save itajaja/7507120 to your computer and use it in GitHub Desktop.
TrulyObservableCollection fires collectionchanged also when items change
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
namespace Hylasoft.OrdersGui.Utils
{
public class TrulyObservableCollection<T> : ObservableCollection<T>
where T : INotifyPropertyChanged
{
public TrulyObservableCollection()
{
CollectionChanged += TrulyObservableCollection_CollectionChanged;
}
void TrulyObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Object item in e.NewItems)
{
(item as INotifyPropertyChanged).PropertyChanged += item_PropertyChanged;
}
}
if (e.OldItems != null)
{
foreach (Object item in e.OldItems)
{
(item as INotifyPropertyChanged).PropertyChanged -= item_PropertyChanged;
}
}
}
void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
var a = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
OnCollectionChanged(a);
}
}
}
@maztan
Copy link

maztan commented Apr 6, 2019

Your implementation is great and I did introduce new event too, at first. Then I discovered that this new event won't work with BindingOperations.EnableCollectionSynchronization(...), no queuing of those events on GUI thread would occur for example. This makes me feel that without some serious re-implementation the easiest solution is to inherit from NotifyCollectionChangedEventArgs and add "PropertyName" property. Next, use this new args class when rising CollectionChanged event and check for that type in the handlers.

    public class CollectionItemPropertyChangedEventArgs : NotifyCollectionChangedEventArgs
    {

        public CollectionItemPropertyChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem, int index, string itemPropertyName)
            : base(action, newItem, oldItem, index)
        {
            PropertyName = itemPropertyName ?? throw new ArgumentNullException(nameof(itemPropertyName));
        }

        //
        // Summary:
        //     Gets the name of the collection item's property that changed.
        //
        // Returns:
        //     The name of the collection item's property that changed.
        public virtual string PropertyName { get; }
    }

And when rising the event:

private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    NotifyCollectionChangedEventArgs args = new CollectionItemPropertyChangedEventArgs(
        NotifyCollectionChangedAction.Replace, sender, sender, IndexOf((T)sender), e.PropertyName);
    OnCollectionChanged(args);
}

And in handler:

private void MappingEntryModel_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
      if (e is CollectionItemPropertyChangedEventArgs e1)
      {
           if (e1.PropertyName == "SomeProperty")
           {
                //deal with item property change
           }
       }
}

@lgaudouen
Copy link

Do you have the latest version of this excellent source?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment