.Net'te ObservableCollection kullanımı nedir?


227

.Net'te ObservableCollection kullanımı nedir?


1
@ alpha-mouse: Çözmeye çalıştığınız sorun hakkında biraz daha bilgi verebilir misiniz? Bu, insanların size ilgili örnekler vermesine yardımcı olacaktır.
Kasım'da Jazza

@Jazza: Sorunun etiketlerini yeni değiştirdim =) Santosh'in sorusu değilim
alpha-mouse

3
@TheMuffinMan doğru, ancak MSDN'in kendi yaratımlarını açıklamanın resmi ve katı yoluna kıyasla şeylerin yığın akışı üzerinde açıklanma şeklini tercih ederim.
Sizons

Yanıtlar:


224

ObservableCollection, koleksiyonun dışındaki kodun koleksiyonda değişiklik (ekleme, taşıma, kaldırma) gerçekleştiğinde farkında olmasını sağlayan bir koleksiyondur. WPF ve Silverlight'ta yoğun olarak kullanılır, ancak kullanımı sadece bununla sınırlı değildir. Kod, koleksiyonun ne zaman değiştiğini görmek için olay işleyicileri ekleyebilir ve daha sonra bazı ek işlemler yapmak için olay işleyicisine tepki verebilir. Bu bir kullanıcı arayüzünü değiştiriyor veya başka bir işlem yapıyor olabilir.

Aşağıdaki kod gerçekten hiçbir şey yapmaz, ancak bir sınıfa bir işleyici nasıl ekleyeceğinizi ve daha sonra değişikliklere bir şekilde tepki vermek için olay argümanlarını nasıl kullanacağınızı gösterir. WPF'de yerleşik UI'yi yenileme gibi birçok işlem var, böylece ObservableCollections'ı kullanırken bunları ücretsiz olarak alabilirsiniz

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.OldsItemseyleme bağlı olarak boş olabilir. Atar NullReferenceException.
dovid

7
sidenote: Action Move olduğunda, taşınan öğe hem NewItems hem de OldItems'te görünecektir
bohdan_trotsenko

Bunun için teşekkür ederiz:> WPF zaten yerleşik kullanıcı arayüzünü yenilemek gibi birçok işleme sahiptir, bu nedenle ObservableCollections
SlowLearner

157

Bir ObservableCollectionarayüz temel olarak düzenli bir koleksiyon gibi çalışır, ancak arayüzleri uygular:

Bu nedenle, koleksiyonun ne zaman değiştiğini bilmek istediğinizde çok kullanışlıdır. Kullanıcıya hangi girişlerin eklendiğini / kaldırıldığını veya taşındığını bildiren bir olay tetiklenir.

Daha da önemlisi, bir form üzerinde veritabanını kullanırken çok kullanışlıdır.


54

Gönderen Pro C # 5.0 ve .NET 4.5 Framework

ObservableCollection<T>Sınıf (çalışırken, tahmin edeceğiniz gibi bu içeriği bir şekilde değişiklik olduğunda harici nesneleri bilgilendirmek yeteneğine sahip olduğunu çok faydalıdır ReadOnlyObservableCollection<T>çok benzer, ancak salt okunur doğada). Birçok açıdan, bu sınıfların her ikisinin de aynı çekirdek arabirimleri uyguladığı göz önüne alındığında, ObservableCollection<T>ile çalışmak aynıdır List<T>. ObservableCollection<T>Sınıfı benzersiz kılan, bu sınıfın adlı bir olayı desteklemesidir CollectionChanged. Bu olay, yeni bir öğe eklendiğinde, geçerli bir öğe kaldırıldığında (veya yeniden konumlandırıldığında) veya tüm koleksiyon değiştirildiğinde tetiklenir. Her etkinlik gibi, CollectionChanged de bu durumda olan bir temsilci olarak tanımlanır NotifyCollectionChangedEventHandler. Bu temsilci, bir nesneyi ilk parametre olarak alan herhangi bir yöntemi veNotifyCollectionChangedEventArgsikinci olarak. Person nesnelerini içeren ve CollectionChangedolayı kablolayan gözlemlenebilir bir koleksiyonu dolduran aşağıdaki Main () yöntemini düşünün :

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

Gelen NotifyCollectionChangedEventArgsparametresi, iki önemli özelliği tanımlar OldItemsve NewItemsbu, etkinlik başlatılmadan önce koleksiyonda bulunan öğelerin ve değişikliğe dahil olan yeni öğelerin bir listesini verir. Ancak, bu listeleri yalnızca doğru koşullar altında incelemek isteyeceksiniz. Öğeler eklendiğinde, kaldırıldığında, taşındığında veya sıfırlandığında CollectionChanged olayının tetiklenebileceğini hatırlayın. Bu eylemlerden hangisinin olayı tetiklediğini keşfetmek için NotifyCollectionChangedEventArgs öğesinin Action özelliğini kullanabilirsiniz. Action özelliği, NotifyCollectionChangedActionnumaralandırmanın aşağıdaki üyelerinden herhangi birine karşı test edilebilir :

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

System.Collections.ObjectModel üyeleri


1
Koleksiyondaki bir kişinin adını değiştirirsem people_CollectionChanged olayı tetiklenir mi (koleksiyonun kendisini değiştirmeden?)
BKSpurgeon

25

Kodsuz açıklama

Arkasında herhangi bir kod olmadan cevap vermek isteyenler için (boom-tish) elimi kaldırırım:

Normal Koleksiyonlar - Bildirim Yok

Arada sırada NYC'ye gidiyorum ve eşim bir şeyler almamı istiyor. Bu yüzden yanımda bir alışveriş listesi alıyorum. Listede şu gibi birçok şey var:

  1. Louis Vuitton çanta (5000 dolar)
  2. Clive Christian'ın İmparatorluk Majesteleri Parfümü (215.000 $)
  3. Gucci Güneş Gözlüğü (2000 $)

hahaha iyi ben bu şeyleri satın değilim. Bu yüzden onları çapraz ve listeden kaldırmak ve bunun yerine eklemek:

  1. 12 düzine Titleist golf topu.
  2. 12 lb bowling topu.

Bu yüzden genellikle malları olmadan eve gelirim ve asla memnun olmaz. Şey, o listeden ne çıkarmak ve üzerine ne eklediğimi bilmiyor olmasıdır; hiçbir bildirim almaz.

ObservableCollection - değişiklik yapıldığında yapılan bildirimler

Şimdi, listeden bir şey kaldırdığımda: telefonunda bir bildirim alır (yani sms / e-posta vb.)!

Gözlenebilir koleksiyon da aynı şekilde çalışır. Bir şey ekler veya bu öğeden bir şey ekler veya kaldırırsanız: birisi bilgilendirilir. Ve bilgilendirildiklerinde, o zaman sizi ararlar ve bir kulak dolusu alırsınız. Tabii ki sonuçlar olay giderici aracılığıyla özelleştirilebilir.

Bu her şeyi özetliyor!


7

En büyük kullanımlardan biri, kullanıcı arabirimi bileşenlerini birine bağlayabilmenizdir ve koleksiyonun içeriği değişirse uygun şekilde yanıt verir. Örneğin, ListView'ın ItemsSource'unu birine bağlarsanız, koleksiyonu değiştirirseniz ListView içeriği otomatik olarak güncellenir.

EDIT: İşte MSDN'den bazı örnek kod: http://msdn.microsoft.com/en-us/library/ms748365.aspx

C # 'da, ListBox'ı koleksiyona bağlamak kadar kolay olabilir

listBox.ItemsSource = NameListData;

listeyi statik bir kaynak olarak bağlamadıysanız ve NameItemTemplate'i tanımladıysanız, PersonName'in ToString () yöntemini geçersiz kılmak isteyebilirsiniz. Örneğin:

public override ToString()
{
    return string.Format("{0} {1}", this.FirstName, this.LastName);
}

6

koleksiyonda çoğunlukla kullanıcı arayüzünü değiştirmek için kullanılan bir koleksiyon, otomatik bildirimi destekler.

Temelde WPF,

Diyelim ki bir liste kutusuyla UI'niz var ve düğme ekle ve o düğmeyi tıkladığınızda, obseravablecollection türüne bir nesne ekleneceğini ve bu koleksiyonu Liste Kutusuna ItemSource'a bağladığınızı varsayalım. Koleksiyondaki yeni öğe, Liste Kutusu kendisini güncelleyecek ve içine bir öğe daha ekleyecektir.


gerçekten bu olur ?? : 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();
}

Neden FooObservableCollection koleksiyonunun uygulandığını açıklayabilir misiniz? Ve neden InsertItem'i yumurtladın?
Arie

@Arie: dürüst olmak gerekirse, 8 yıl sonra hatırlamıyorum, bu yüzden hiçbir fikrim yok. Dokümanlarda gördüğümden , bunlara gerek yok, hepsi kutudan çıkmalı.
abatishchev
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.