1
\$\begingroup\$

This is an extension of the System.ComponentModel.BindingList<T> class that allows for notifications of item changing and deleting. These notifications provided the outgoing item and the incoming item, as well as a Cancel property to cancel the change or deletion.

In additon, it also allows for a bulk addition of items, which is just a loop of AddItem (which will trigger a change notification for each item added).

On top of bulk addition, there is a SetItems which will clear the collection and add all the items provided, but will only fire one Reset notification.

using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace BindingListExtension
{
    public class BindingListEx<T> : BindingList<T>
    {
        public event EventHandler<ListItemRemovingEventArgs<T>> ListItemRemoving;
        public event EventHandler<ListItemChangingEventArgs<T>> ListItemChanging;

        protected override void RemoveItem(int index)
        {
            var args = new ListItemRemovingEventArgs<T>(this[index], index);
            ListItemRemoving?.Invoke(this, args);
            if (args.Cancel) return;
            base.RemoveItem(index);
        }

        protected override void SetItem(int index, T item)
        {
            var args = new ListItemChangingEventArgs<T>(this[index], item, index);
            ListItemChanging?.Invoke(this, args);
            if (args.Cancel) return;
            base.SetItem(index, item);
        }

        public void SetItems(IEnumerable<T> items)
        {
            RaiseListChangedEvents = false;
            Clear();
            AddItems(items);
            RaiseListChangedEvents = true;
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

        public void AddItems(IEnumerable<T> items)
        {
            if (items != null)
            {
                foreach (T item in items)
                {
                    Add(item);
                }
            }
        }
    }

    public class ListItemRemovingEventArgs<T> : CancelEventArgs
    {
        public ListItemRemovingEventArgs(T oldItem, int index)
        {
            OldItem = oldItem;
        }

        public T OldItem { get; }

        public int Index { get; }
    }

    public class ListItemChangingEventArgs<T> : ListItemRemovingEventArgs<T>
    {
        public ListItemChangingEventArgs(T oldItem, T newItem, int index) : base(oldItem, index)
        {
            NewItem = newItem;
        }

        public T NewItem { get; }
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ There is not need for a new type. Since RaiseListChangedEvents is a public property both methods (SetItems & AddItems) could be extension methods. I find the behaviour of SetItems is pretty unexpected because it clears the collection and not like the original SetItem updates items at specific indexes which it should be doing. What you have written is more like ResetItems and you seem to have forgotten to disable rasing events in AddItems. \$\endgroup\$ – t3chb0t Feb 10 '19 at 9:04
  • \$\begingroup\$ @t3chb0t I believe Add calls SetItem internally (not sure), so an event is raised. \$\endgroup\$ – dfhwze Aug 17 '19 at 22:00
1
\$\begingroup\$

ListChangedType.Reset

AddItems is nothing more than a glorified wrapper method for calling Add multiple times. However, guidelines suggest that ListChangedType.Reset could and probably should also be called here. Since Reset should be called when..

Much of the list has changed. Any listening controls should refresh all their data from the list.

To give this method some purpose other than looping elements and call Add, consider using the same deferral strategy as you did with SetItems.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.