У чому полягає використання ObservableCollection в .net?


227

У чому полягає використання ObservableCollection в .net?


1
@ альфа-миша: Чи можете ви дати трохи більше інформації про проблему, яку ви намагаєтеся вирішити? Це допоможе людям навести відповідні приклади.
Jazza

@Jazza: Я щойно змінив теги питання =) Я не запитую Сантоша
альфа-миша

3
@TheMuffinMan правда, але я віддаю перевагу тому, як все пояснюється на stackoverflow, порівняно із занадто жорстким формальним способом 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.
довід

7
sidenote: коли Action буде рухатися, переміщений елемент з’явиться як у NewItems, так і в OldItems
bohdan_trotsenko

Дякую за це:> У WPF вже є багато операцій, таких як оновлення інтерфейсу користувача, вбудованого, щоб отримати їх безкоштовно при використанні
ObservableCollections

157

Праця ObservableCollectionпо суті схожа на звичайну колекцію, за винятком того, що вона реалізує інтерфейси:

Як такий, це дуже корисно, коли ви хочете дізнатися, коли колекція змінилася. Запускається подія, яка повідомляє користувачеві, які записи були додані / видалені або переміщені.

Що ще важливіше, вони дуже корисні при використанні прив'язки даних у формі.


54

Від Pro C # 5.0 та .NET 4.5 Framework

ObservableCollection<T>Клас дуже корисний тим , що він має можливість інформувати зовнішні об'єкти , коли його зміст змінилося яким - то чином (як ви могли здогадатися, працювати з ReadOnlyObservableCollection<T>дуже схожий, але тільки для читання в природі), Багато в чому робота з the ObservableCollection<T>ідентична роботі з List<T>, враховуючи, що обидва ці класи реалізують однакові основні інтерфейси. Що робить ObservableCollection<T>клас унікальним, це те, що цей клас підтримує назву події CollectionChanged. Ця подія запускається кожного разу, коли новий елемент буде вставлено, поточний елемент буде видалено (або переміщено) або якщо вся колекція буде змінена. Як і будь-яка подія, CollectionChanged визначається через делегата, що в цьому випадку є NotifyCollectionChangedEventHandler. Цей делегат може викликати будь-який метод, який приймає об'єкт як перший параметр, і aNotifyCollectionChangedEventArgsяк другий. Розглянемо наступний метод 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. Духи Імператорської Величності Clive Christian's ($ 215 000)
  3. Сонцезахисні окуляри Gucci (2000 доларів)

так, я не купую ці речі. Тому я перекреслюю їх та видаляю зі списку, а замість цього додаю:

  1. 12 десятків м'ячів для гольфу титулістів
  2. Куля для боулінгу в 12 фунтів.

Тому я зазвичай приходжу додому без товару, і вона ніколи не задоволена. Річ у тім, що вона не знає про те, що я знімаю зі списку і що я додаю до нього; вона не отримує сповіщень.

ObservableCollection - сповіщення про внесення змін

Тепер, коли я щось видалю зі списку: вона отримує сповіщення на свій телефон (тобто sms / email тощо)!

Спостережна колекція працює точно так само. Якщо ви щось додаєте або видалите з нього: хтось отримує сповіщення. І коли вони отримають сповіщення, тоді вони зателефонують вам, і ви отримаєте вухо. Звичайно, наслідки можна налаштувати через обробник подій.

Це все підсумовує!


7

Одне з найбільших застосувань полягає в тому, що ви можете прив’язати компоненти інтерфейсу до одного, і вони відповідатимуть належним чином, якщо зміст вмісту колекції зміниться. Наприклад, якщо ви прив’яжіть ItemSource ListView до одного, вміст ListView автоматично оновиться, якщо ви модифікуєте колекцію.

EDIT: Ось зразок коду з 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

це колекція, яка використовується для сповіщення в основному інтерфейсу користувача про зміну колекції, підтримує автоматичне сповіщення.

В основному використовується в WPF,

Припустимо, припустимо, у вас є інтерфейс користувача зі списком і кнопкою додавання, і при натисканні на кнопку він об'єкт типу, припустимо, людина буде доданий до об'єктивноїколекції, і ви пов'язуєте цю колекцію з ItemSource of Listbox, тому щойно ви додасте новий елемент колекції, Listbox оновить себе і додасть ще один елемент до нього.


справді це відбувається ?? : O
Королі

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();
}

Ви можете пояснити, чому FooObservableCollection реалізував колекцію? І чому ви перекрили InsertItem?
Ар’є

@Arie: Чесно кажучи, через 8 років я не пам'ятаю, так що ідеї немає. З того, що я бачу в документах , немає потреби в цьому, все повинно вийти з коробки.
абатищев
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.