【问题标题】:EntityFramework EntityCollection Observing CollectionChangedEntityFramework EntityCollection 观察 CollectionChanged
【发布时间】:2011-03-31 15:55:20
【问题描述】:

我首先在应用程序中使用 EntityFramework 数据库。我想以某种方式收到关于我的 ViewModel 中 EntityCollection 的更改的通知。它不直接支持INotifyCollectionChanged(为什么?)而且我还没有成功找到另一个解决方案。

这是我最近的尝试,但由于 ListChanged 事件似乎没有被引发,所以它不起作用:

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));
    }
}

有人知道我如何观察EntityCollection 的变化吗?

【问题讨论】:

标签: c# entity-framework inotifycollectionchanged entitycollection


【解决方案1】:

您是否尝试过处理 AssociationChanged 在对相关端进行更改时发生。 (继承自 RelatedEnd。)

它提供参数来显示一个元素是被添加还是被删除,并且还暴露了元素。

【讨论】:

    【解决方案2】:

    虽然它在 @Aron 指出的简单用例中工作,但我无法让它在我的实际应用程序中正常工作。

    事实证明,出于某种我不确定的原因 - EntityCollection 的内部 IBindingList 不知何故,在某处可以改变。没有调用我的观察员的原因是因为他们正在寻找旧的 IBindingList 的更改,甚至不再被 EntityCollection 使用。

    这是让它为我工作的黑客:

    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));
        }
    }
    

    【讨论】:

    • 伙计,这似乎需要做很多工作......我想知道内部列表是如何改变的。您没有在外部某处更改它吗?太奇怪了。
    • 我从来没有弄清楚何时或为什么要更改它。由于没有监视内部列表何时更改,即使上述解决方案也不可靠。我现在已经迁移到 STE,并且很高兴使用 TrackableCollection。
    【解决方案3】:

    您如何映射事件?粘贴您的代码并像下面这样映射事件对我有用。

    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");
        }
    

    【讨论】:

    • 事实证明,它并不适用于所有情况。请参阅下面的答案,了解适合我的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 2014-03-24
    相关资源
    最近更新 更多