开发者

EntityFramework EntityCollection Observing CollectionChanged

开发者 https://www.devze.com 2023-02-21 18:54 出处:网络
I\'m using EntityFramework database first in an application. I would like somehow to be notified of changes to an EntityCollection in my ViewModel. It doesn\'t directly support INotifyCollectionChange

I'm using EntityFramework database first in an application. I would like somehow to be notified of changes to an EntityCollection in my ViewModel. It doesn't directly support INotifyCollectionChanged (why?) and I haven't been successful in finding another solution.

Here's my latest attempt, which doesn't work because the ListChanged event doesn't appear to get raised:

public class EntityCollectionObserver<T> : ObservableCollection<T>, INotifyCollectionChanged where T : class
{
    public event NotifyCollectionChangedEventHandler CollectionChanged;

    public EntityCollectionObserver(EntityCollection<T> entityCollection)
        : base(entityCollection)
    {
        IBindingList l = ((IBindingList)((IListSource)entityCollection).GetList());
        l.ListChanged += new ListChangedEventHandler(OnInnerListChanged);
    }

    private void OnInnerListChanged(object sender, ListChangedEventArgs e)
    {
        if (CollectionChanged != null) 
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
}

Does anyone have any ideas how I m开发者_Python百科ight observe changes to an EntityCollection?

Dan


have you tried handling AssociationChanged Occurs when a change is made to a related end. (Inherited from RelatedEnd.)

It gives arguments showing whether an element was added or deleted and also exposes the element.


Whilst it worked in the simple use case noted by @Aron, I couldn't get it to work properly in my actual application.

As it turns out, and for reasons I'm not sure - the inner IBindingList of an EntityCollection somehow, somewhere, can get changed. The reason my observers weren't being called is because they were looking for changes on an old IBindingList that wasn't even being used by the EntityCollection any more.

Here is the hack that got it working for me:

public class EntityCollectionObserver<T> : ObservableCollection<T> where T : class
{
    private static List<Tuple<IBindingList, EntityCollection<T>, EntityCollectionObserver<T>>> InnerLists 
        = new List<Tuple<IBindingList, EntityCollection<T>, EntityCollectionObserver<T>>>();

    public EntityCollectionObserver(EntityCollection<T> entityCollection)
        : base(entityCollection)
    {
        IBindingList l = ((IBindingList)((IListSource)entityCollection).GetList());
        l.ListChanged += new ListChangedEventHandler(OnInnerListChanged);


        foreach (var x in InnerLists.Where(x => x.Item2 == entityCollection && x.Item1 != l))
        {
            x.Item3.ObserveThisListAswell(x.Item1);
        }
        InnerLists.Add(new Tuple<IBindingList, EntityCollection<T>, EntityCollectionObserver<T>>(l, entityCollection, this));
    }

    private void ObserveThisListAswell(IBindingList l)
    {
        l.ListChanged += new ListChangedEventHandler(OnInnerListChanged);
    }

    private void OnInnerListChanged(object sender, ListChangedEventArgs e)
    {
        base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
}


How are you mapping the event? Pasting your code and mapping the event like follows works for me.

static void Main(string[] args)
    {
        EntityCollection<string> col = new EntityCollection<string>();
        EntityCollectionObserver<string> colObserver = new EntityCollectionObserver<string>(col);

        colObserver.CollectionChanged += colObserver_CollectionChanged;

        col.Add("foo");
    }

    static void colObserver_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        Console.WriteLine("Entity Collection Changed");
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消