Выполнение кода при изменении коллекции (элементы добавлены или удалены) - PullRequest
2 голосов
/ 16 декабря 2008

У меня есть класс, который содержит список объектов. Каков наилучший способ запустить некоторый код в классе, когда список изменен?

class MyManagerClass
{
    ArrayList list = new ArrayList(); // will likely be a different collection class
    private OnItemAddedToList(object o)
    {
        // how to call this?
    }

    private OnItemRemovedFromList(object o)
    {
        // how to call this?  
    }
}

Ответы [ 6 ]

5 голосов
/ 16 декабря 2008

Если вы все равно пишете собственные коллекции, вы можете реализовать интерфейсы INotifyCollectionChanged или INotifyPropertyChanged. Они добавляют события, на которые вы можете подписаться, которые уведомляют слушателя, когда данные коллекций изменяются каким-либо образом.
Делая это, вы можете подписаться на события в коде за пределами вашей коллекции.

В качестве альтернативы вы можете использовать класс ObservableCollection<T>, который реализует оба этих интерфейса. Оба интерфейса INotifyCollectionChanged и ObservableCollection<T> доступны только в .Net Framework 3.0 и более поздних версиях.

В .Net Framework 2.0 вы можете использовать интерфейс IBindingList для получения той же функциональности, но его сложнее реализовать, чем интерфейс INotifyCollectionChanged в 3.0

3 голосов
/ 16 декабря 2008

Вы также можете рассмотреть возможность использования класса System.Collections.ObjectModel.ObservableCollection<T>, который предоставляет вам это в форме события CollectionChanged, которое дает вам информацию об изменениях.

2 голосов
/ 16 декабря 2008

В 2.0 и выше есть BindingList<T>, который имеет все необходимые крючки для наблюдаемой коллекции. Также существует (как уже упоминалось) класс ObservableCollection<T>, который очень похож.

Получение новой коллекции из Collection<T> также довольно разумно во многих обстоятельствах. Но не наследуйте от List<T>, поскольку в нем нет (полезных) виртуальных методов.

2 голосов
/ 16 декабря 2008

Метод, который я использовал до сих пор, заключается в создании класса частной коллекции, полученного из System.Collections.ObjectModel.Collection<T>, и вызове методов непосредственно в переопределениях:

class MyManagerClass
{
    private class MyCollection : System.Collections.ObjectModel.Collection<object>
    {
        private MyManagerClass manager;

        private MyCollection(MyManagerClass manager)
        {
            this.manager = manager;
        }

        protected override void InsertItem(int index, object item)
        {
            base.InsertItem(index, item);
            manager.OnItemAddedToList(item);
        }

        protected override void SetItem(int index, object item)
        {
            object oldItem = (index < base.Count) ? base[index] : null;
            base.SetItem(index, item);

            if (oldItem != null) {
                manager.OnItemRemovedFromList(oldItem);
            }

            manager.OnItemAddedToList(item);
        }

        protected override void RemoveItem(int index, object item)
        {
            base.RemoveItem(index, item);
            manager.OnItemRemovedFromList(item);
        }
    }

    private OnItemAddedToList(object o)    
    {
    }

    private OnItemRemovedFromList(object o)    
    {
    }
}

Я не уверен, является ли это правильным способом сделать это, хотя, и я хотел бы видеть, есть ли лучшие альтернативы.

1 голос
/ 16 декабря 2008

Вместо использования ArrayList из System.Collections вы должны рассмотреть возможность использования ArrayList из C5 Generic Collection Library . Он имеет такие события, как CollectionChanged, ItemAdded и т. Д.

0 голосов
/ 16 декабря 2008

Лично я бы реализовал IList<T> в классе, который имеет Added, Removed и Replaced события / делегаты. Класс будет иметь закрытый экземплярный экземпляр типа List<T>, которому будут делегированы все реализованные вызовы, а также вызов события.

Вы можете дополнительно иметь OnBefore..., OnAfter, если хотите, что позволит вам "отменить" добавление / удаление элементов.

Обычно это так, но, как сказал mookid, вероятно, существуют существующие библиотеки, которые делают аналогичные вещи. Класс DataTable реализует аналогичную концепцию с классом DataRow, включая добавление, удаление и обновление.

Вы можете объединить понятия, чтобы элементы, добавленные в коллекцию, могли вызывать OnChanged события, которые «всплывают» в коллекцию и могут использоваться для повторного вызова события ItemChanged в коллекции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...