Какая польза от ObservableCollection в .net?

227

Какая польза от ObservableCollection в .net?

Сантош Сингх
источник
1
@ alpha-mouse: Можете ли вы дать немного больше информации о проблеме, которую вы пытаетесь решить? Это поможет людям привести соответствующие примеры.
Джазза
@Jazza: Я только что изменил теги вопроса =) Я не вопрос Сантоша
альфа-мышь
3
@TheMuffinMan верно, но я предпочитаю, как все объясняется в стеке, а не в MSDN слишком жестко, чтобы формально объяснять свои собственные создания.
Сизонс

Ответы:

224

ObservableCollection - это коллекция, которая позволяет коду вне коллекции знать, когда происходят изменения в коллекции (добавление, перемещение, удаление). Он широко используется в WPF и Silverlight, но его использование не ограничивается этим. Код может добавить обработчики событий, чтобы видеть, когда коллекция изменилась, и затем реагировать через обработчик событий, чтобы выполнить некоторую дополнительную обработку. Это может быть изменение пользовательского интерфейса или выполнение какой-либо другой операции.

Приведенный ниже код ничего не делает, но демонстрирует, как вы присоединяете обработчик к классу, а затем используете аргументы события, чтобы каким-то образом реагировать на изменения. В WPF уже есть много операций, таких как обновление встроенного пользовательского интерфейса, поэтому вы получаете их бесплатно при использовании ObservableCollections

class Handler
{
    private ObservableCollection<string> collection;

    public Handler()
    {
        collection = new ObservableCollection<string>();
        collection.CollectionChanged += HandleChange;
    }

    private void HandleChange(object sender, NotifyCollectionChangedEventArgs e)
    {
        foreach (var x in e.NewItems)
        {
            // do something
        }

        foreach (var y in e.OldItems)
        {
            //do something
        }
        if (e.Action == NotifyCollectionChangedAction.Move)
        {
            //do something
        }
    }
}
Крейг Суханец
источник
21
e.NewItems& e.OldsItemsможет быть нулевым в зависимости от действия. Это может бросить NullReferenceException.
DOVID
7
sidenote: когда Action is Move, перемещенный элемент будет отображаться как в NewItems, так и в OldItems
bohdan_trotsenko
Спасибо вам за это:> В WPF уже есть много операций, таких как обновление встроенного пользовательского интерфейса, так что вы получаете их бесплатно при использовании ObservableCollections
SlowLearner
157

An ObservableCollectionработает по сути как обычная коллекция, за исключением того, что он реализует интерфейсы:

Таким образом, это очень полезно, когда вы хотите знать, когда коллекция изменилась. Инициируется событие, которое сообщит пользователю, какие записи были добавлены / удалены или перемещены.

Что еще более важно они очень полезны при использовании привязки данных на форме.

Лиз
источник
54

Из Pro C # 5.0 и .NET 4.5 Framework

ObservableCollection<T>Класс очень полезен тем , что он имеет возможность информировать внешние объекты , когда его содержание изменилось каким - то образом (как вы могли догадаться, работать с ReadOnlyObservableCollection<T>очень похожи, но только для чтения в природе). Во многих отношениях работа с ними ObservableCollection<T>идентична работе с List<T>учетом того, что оба эти класса реализуют одни и те же основные интерфейсы. Что делает ObservableCollection<T>класс уникальным, так это то, что этот класс поддерживает событие с именем CollectionChanged. Это событие будет срабатывать всякий раз, когда вставляется новый элемент, текущий элемент удаляется (или перемещается), или если вся коллекция изменяется. Как и любое событие, CollectionChanged определяется в терминах делегата, который в данном случае является NotifyCollectionChangedEventHandler. Этот делегат может вызывать любой метод, который принимает объект в качестве первого параметра, иNotifyCollectionChangedEventArgsкак второй. Рассмотрим следующий метод Main (), который заполняет наблюдаемую коллекцию, содержащую объекты Person, и связывает CollectionChangedсобытие:

class Program
{
   static void Main(string[] args)
   {
     // Make a collection to observe and add a few Person objects.
     ObservableCollection<Person> people = new ObservableCollection<Person>()
     {
        new Person{ FirstName = "Peter", LastName = "Murphy", Age = 52 },
        new Person{ FirstName = "Kevin", LastName = "Key", Age = 48 },
     };
     // Wire up the CollectionChanged event.
     people.CollectionChanged += people_CollectionChanged;
     // Now add a new item.
     people.Add(new Person("Fred", "Smith", 32));

     // Remove an item.
     people.RemoveAt(0);

     Console.ReadLine();
   }
   static void people_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
   {
       // What was the action that caused the event?
        Console.WriteLine("Action for this event: {0}", e.Action);

        // They removed something. 
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
        {
            Console.WriteLine("Here are the OLD items:");
            foreach (Person p in e.OldItems)
            {
                Console.WriteLine(p.ToString());
            }
            Console.WriteLine();
        }

        // They added something. 
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
        {
            // Now show the NEW items that were inserted.
            Console.WriteLine("Here are the NEW items:");
            foreach (Person p in e.NewItems)
            {
                Console.WriteLine(p.ToString());
            }
        }
   }
}

Входящий NotifyCollectionChangedEventArgsпараметр определяет два важных свойства, OldItemsи NewItems, который предоставит вам список элементов, которые в данный момент находились в коллекции до возникновения события, и новые элементы, которые были вовлечены в изменение. Тем не менее, вы захотите изучить эти списки только при правильных обстоятельствах. Напомним, что событие CollectionChanged может возникать при добавлении, удалении, перемещении или сбросе элементов. Чтобы узнать, какое из этих действий вызвало событие, вы можете использовать свойство Action объекта NotifyCollectionChangedEventArgs. Свойство Action может быть проверено на соответствие любому из следующих элементов NotifyCollectionChangedActionперечисления:

public enum NotifyCollectionChangedAction
{
Add = 0,
Remove = 1,
Replace = 2,
Move = 3,
Reset = 4,
}

Члены System.Collections.ObjectModel

Саид Роохулла Аллем
источник
1
произойдет ли событие people_CollectionChanged, если я изменю имя человека в коллекции (не изменяя саму коллекцию?)
BKSpurgeon
25

Объяснение без кода

Для тех, кто хочет получить ответ без какого-либо кода (бум-тиш), я подниму руку:

Обычные Коллекции - Нет Уведомлений

Время от времени я иду в Нью-Йорк, и моя жена просит меня купить вещи. Поэтому я беру список покупок с собой. В списке есть много вещей, таких как:

  1. Сумочка Louis Vuitton ($ 5000)
  2. Духи Императорского Величества Клайва Кристиана ($ 215 000)
  3. Солнцезащитные очки Gucci ($ 2000)

Хахаха, я не покупаю эти вещи. Поэтому я вычеркиваю их, удаляю из списка и добавляю:

  1. 12 десятков титульных мячей для гольфа.
  2. 12 фунтов мяч для боулинга.

Поэтому я обычно прихожу домой без товаров, а она никогда не радуется. Дело в том, что она не знает о том, что я исключаю из списка и что я к нему добавляю; она не получает уведомлений.

The ObservableCollection - уведомления о внесенных изменениях

Теперь, когда я удаляю что-то из списка: она получает уведомление на свой телефон (например, смс / электронная почта и т. Д.)!

Наблюдаемая коллекция работает точно так же. Если вы добавляете или удаляете что-либо в или из него: кто-то получает уведомление. И когда они будут уведомлены, ну, тогда они позвонят вам, и вы получите полный слух. Конечно, последствия настраиваются через обработчик событий.

Это подводит итог всего этого!

BKSpurgeon
источник
7

Одним из наиболее важных применений является то, что вы можете привязать компоненты пользовательского интерфейса к одному, и они будут реагировать соответствующим образом, если содержимое коллекции изменится. Например, если вы связываете ListSource ItemsSource с одним из них, содержимое ListView будет автоматически обновляться при изменении коллекции.

РЕДАКТИРОВАТЬ: Вот пример кода из MSDN: http://msdn.microsoft.com/en-us/library/ms748365.aspx

В C # подключить ListBox к коллекции можно так же просто, как

listBox.ItemsSource = NameListData;

хотя, если вы не подключили список как статический ресурс и не определили NameItemTemplate, вы можете переопределить ToString () PersonName. Например:

public override ToString()
{
    return string.Format("{0} {1}", this.FirstName, this.LastName);
}
Шон У
источник
6

это коллекция, которая используется для уведомления в основном UI об изменениях в коллекции, она поддерживает автоматическое уведомление.

В основном используется в WPF,

Где, скажем, предположим, что у вас есть пользовательский интерфейс со списком и кнопкой добавления, и когда вы нажимаете на кнопку он, объект типа предположим, что человек будет добавлен в коллекцию obseravablecollection, и вы привяжете эту коллекцию к ItemSource of Listbox, так как только вы добавите Новый элемент в коллекции, Listbox обновится и добавит в него еще один элемент.

TalentTuner
источник
неужели это происходит ?? : O
Kings
5
class FooObservableCollection : ObservableCollection<Foo>
{
    protected override void InsertItem(int index, Foo item)
    {
        base.Add(index, Foo);

        if (this.CollectionChanged != null)
            this.CollectionChanged(this, new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, item, index);
    }
}

var collection = new FooObservableCollection();
collection.CollectionChanged += CollectionChanged;

collection.Add(new Foo());

void CollectionChanged (object sender, NotifyCollectionChangedEventArgs e)
{
    Foo newItem = e.NewItems.OfType<Foo>().First();
}
abatishchev
источник
Вы можете объяснить, почему в FooObservableCollection реализована коллекция? И почему вы ovverided InsertItem?
Арье
@ Арье: честно, спустя 8 лет я не помню, так что понятия не имею. Из того, что я вижу в документах, нет необходимости в этом, все должно быть из коробки.
Абатищев