26

我有一个类继承自ObservableCollection并添加了一些其他方法,例如AddRangeRemoveRange

我的基本方法调用是这样的:

public void AddRange(IEnumerable<T> collection)
{
    foreach (var i in collection) Items.Add(i);

    OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}

我的问题是我想访问e.NewItemse.OldItemsCollectionChanged事件中对集合中的任何项目执行操作,并且该NotifyCollectionChangedAction.Reset操作没有传递这些值

void Instances_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.NewItems != null) // e.NewItems is always null
    {
        foreach (var item in e.NewItems)
        {
            if (item is EventInstanceModel)
                ((EventInstanceModel)item).ParentEvent = this;
        }
    }
}

所以我想我可以只使用NotifyCollectionChangedAction.Add而不是Reset,但是会引发Range actions are not supported异常

public void AddRange(IEnumerable<T> collection)
{
    var addedItems = collection.ToList();
    foreach (var i in addedItems) Items.Add(i);

    OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, addedItems));
}

所以我的问题是,我怎样才能引发一个 CollectionChanged 事件,并将它传递给新的或旧的项目列表?

4

3 回答 3

19

我一直在研究它,显然该CollectionChanged方法不能用多个项目提出。

所以我可以打电话

OnCollectionChanged(new NotifyCollectionChangedEventArgs(
    NotifyCollectionChangedAction.Add, singleItem));

但我不能打电话

OnCollectionChanged(new NotifyCollectionChangedEventArgs(
    NotifyCollectionChangedAction.Add, listOfItems));

现在我所做的只是为添加的每个项目引发 Add 事件,但我对此仍然相当不满意,因为这意味着我为方法CollectionChanged中的每个项目引发事件,AddRange而不是只引发一次。

public void AddRange(IEnumerable<T> collection)
{
    foreach (var i in collection) 
    {
        Items.Add(i);
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(
            NotifyCollectionChangedAction.Add, i));
    }
}
于 2011-09-16T19:22:31.397 回答
5

这对我来说“独立”很好。这意味着我没有使用ObservableCollection数据绑定。所以这不是ObservableCollection问题,而是ListCollectionView限制。

请阅读以下文章,这是一个非常有趣的阅读:

内森·内斯比特的博客

于 2011-09-16T19:36:23.517 回答
0

如果您将鼠标悬停NotifyCollectionChangedEventArgs在上下文弹出窗口中并选择“转到定义”,则事件类的文档非常不错。在打开的元数据文件中,您可以展开摘要以查看哪些操作与哪些构造函数配合使用。例如:

元数据文件示例

您还可以创建一个简单的继承它的自定义类,您可以做任何您想做的事情。我们的用例(类似于操作)需要一个 Reset 事件来报告已删除的内容。自定义事件类如下所示:

public class NotifyCollectionResetEventArgs : NotifyCollectionChangedEventArgs
{
    public NotifyCollectionResetEventArgs(List<object> removedItems) 
        : base(action: NotifyCollectionChangedAction.Reset)
    {
        RemovedItems = removedItems.ToList();
    }
    public List<object> RemovedItems { get; }
}

继承 ObservableCollection 的类重写了 Clear 方法:

public class ObservableAttributeValueCollection : ObservableCollection<object>
{
    List<object> _removedItems = null;
    public new void Clear()
    {
        _removedItems = Items.ToList<object>(); // 1. Capture the items.
        base.Clear();                           // 2. Clear the items
        _removedItems = null;                   // 3. Clean up
    }
    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if(e.Action == NotifyCollectionChangedAction.Reset)
        {
            base.OnCollectionChanged(new NotifyCollectionResetEventArgs(_removedItems));
        }
        else
        {
            base.OnCollectionChanged(e);
        }
    }
}

最后,在处理程序中使用此事件使用“is”模式来分配ePlus变量。

void handleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
    {
        case NotifyCollectionChangedAction.Reset:
            if (e is NotifyCollectionResetEventArgs ePlus)
            {
                foreach (var item in ePlus.RemovedItems)
                {
                    // Do Something
                }
            }
            break;
    }
}
于 2022-02-22T21:52:37.300 回答