首页 >后端开发 >C++ >如何将 AddRange 方法和 INotifyCollectionChanging 添加到 .NET 中的 ObservableCollection?

如何将 AddRange 方法和 INotifyCollectionChanging 添加到 .NET 中的 ObservableCollection?

Barbara Streisand
Barbara Streisand原创
2025-01-20 07:22:12527浏览

How to Add an AddRange Method and INotifyCollectionChanging to an ObservableCollection in .NET?

.NET中的ObservableCollection类提供了一个动态数据集合,可以在添加、删除或重新排列项时发出通知。但是,它缺少AddRange方法,该方法无法一次批量添加多个项。此外,INotifyCollectionChanging接口可用于在更改提交到集合之前跟踪更改,从而提供取消更改的机会。

以下是如何在ObservableCollection中实现AddRange方法并集成INotifyCollectionChanging

C#:

<code class="language-csharp">using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Collections.Specialized;

public class ObservableRangeCollection<T> : ObservableCollection<T>, INotifyCollectionChanging<T>
{
    public event NotifyCollectionChangingEventHandler<T> CollectionChanging;

    protected override void OnCollectionChanging(NotifyCollectionChangingEventArgs e)
    {
        // 创建一个包含更改信息的事件参数
        var typedEventArgs = new NotifyCollectionChangingEventArgs<T>(e.Action, e.NewItems != null ? (IEnumerable<T>)e.NewItems : null, e.OldItems != null ? (IEnumerable<T>)e.OldItems : null, e.Index);

        // 触发自定义事件,允许取消操作
        CollectionChanging?.Invoke(this, typedEventArgs);

        // 检查是否取消
        if (typedEventArgs.Cancel)
        {
            return;
        }

        // 调用基类的OnCollectionChanging方法
        base.OnCollectionChanging(e);
    }

    public void AddRange(IEnumerable<T> collection)
    {
        if (collection == null)
        {
            throw new ArgumentNullException(nameof(collection));
        }

        // 触发CollectionChanging事件
        OnCollectionChanging(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collection));

        // 添加项目
        foreach (T item in collection)
        {
            Add(item);
        }
    }
}

//自定义INotifyCollectionChanging接口,用于类型安全
public interface INotifyCollectionChanging<T> : INotifyCollectionChanged
{
    event NotifyCollectionChangingEventHandler<T> CollectionChanging;
}

//自定义事件处理程序,用于类型安全
public delegate void NotifyCollectionChangingEventHandler<T>(object sender, NotifyCollectionChangingEventArgs<T> e);

//自定义事件参数,用于类型安全
public class NotifyCollectionChangingEventArgs<T> : NotifyCollectionChangedEventArgs
{
    public NotifyCollectionChangingEventArgs(NotifyCollectionChangedAction action, IEnumerable<T> newItems) : base(action, newItems) { }
    public NotifyCollectionChangingEventArgs(NotifyCollectionChangedAction action, IEnumerable<T> newItems, IEnumerable<T> oldItems) : base(action, newItems, oldItems) { }
    public NotifyCollectionChangingEventArgs(NotifyCollectionChangedAction action, IEnumerable<T> newItems, int index) : base(action, newItems, index) { }
    public NotifyCollectionChangingEventArgs(NotifyCollectionChangedAction action, T newItem, int index) : base(action, newItem, index) { }
    public NotifyCollectionChangingEventArgs(NotifyCollectionChangedAction action, T oldItem, int index) : base(action, null, oldItem, index) { }
    public bool Cancel { get; set; }
}</code>

VB.NET:

<code class="language-vb.net">Imports System
Imports System.Collections.ObjectModel
Imports System.Collections.Generic
Imports System.Collections.Specialized
Imports System.ComponentModel

Public Class ObservableRangeCollection(Of T)
    Inherits ObservableCollection(Of T)
    Implements INotifyCollectionChanging(Of T)

    Public Event CollectionChanging As NotifyCollectionChangingEventHandler(Of T) Implements INotifyCollectionChanging(Of T).CollectionChanging

    Protected Overrides Sub OnCollectionChanging(e As NotifyCollectionChangedEventArgs)
        Dim typedEventArgs As New NotifyCollectionChangingEventArgs(Of T)(e.Action, If(e.NewItems IsNot Nothing, DirectCast(e.NewItems, IEnumerable(Of T)), Nothing), If(e.OldItems IsNot Nothing, DirectCast(e.OldItems, IEnumerable(Of T)), Nothing), e.Index)
        RaiseEvent CollectionChanging(Me, typedEventArgs)
        If typedEventArgs.Cancel Then
            Return
        End If
        MyBase.OnCollectionChanging(e)
    End Sub

    Public Sub AddRange(collection As IEnumerable(Of T))
        If collection Is Nothing Then
            Throw New ArgumentNullException("collection")
        End If

        OnCollectionChanging(New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collection))

        For Each item As T In collection
            Add(item)
        Next
    End Sub
End Class

'自定义INotifyCollectionChanging接口,用于类型安全
Public Interface INotifyCollectionChanging(Of T)
    Inherits INotifyCollectionChanged
    Event CollectionChanging As NotifyCollectionChangingEventHandler(Of T)
End Interface

'自定义事件处理程序,用于类型安全
Public Delegate Sub NotifyCollectionChangingEventHandler(Of T)(sender As Object, e As NotifyCollectionChangingEventArgs(Of T))

'自定义事件参数,用于类型安全
Public Class NotifyCollectionChangingEventArgs(Of T)
    Inherits NotifyCollectionChangedEventArgs
    Public Sub New(action As NotifyCollectionChangedAction, newItems As IEnumerable(Of T))
        MyBase.New(action, newItems)
    End Sub
    Public Sub New(action As NotifyCollectionChangedAction, newItems As IEnumerable(Of T), oldItems As IEnumerable(Of T))
        MyBase.New(action, newItems, oldItems)
    End Sub
    Public Sub New(action As NotifyCollectionChangedAction, newItems As IEnumerable(Of T), index As Integer)
        MyBase.New(action, newItems, index)
    End Sub
    Public Sub New(action As NotifyCollectionChangedAction, newItem As T, index As Integer)
        MyBase.New(action, newItem, index)
    End Sub
    Public Sub New(action As NotifyCollectionChangedAction, oldItem As T, index As Integer)
        MyBase.New(action, Nothing, oldItem, index)
    End Sub
    Public Property Cancel As Boolean
End Class</code>

通过这种方法,您可以在能够跟踪并在发生之前取消更改的同时,从批量操作中受益。 代码已改进,使其更健壮,并处理了 INotifyCollectionChanging 事件的类型安全问题。 它还包含了对 OnCollectionChanging 方法的重写,以确保在触发自定义事件后,仍然调用基类的 OnCollectionChanging 方法,从而保证 ObservableCollection 的正常功能。

以上是如何将 AddRange 方法和 INotifyCollectionChanging 添加到 .NET 中的 ObservableCollection?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn