Apa gunanya ObservableCollection di .net?

227

Apa gunanya ObservableCollection di .net?

santosh singh
sumber
1
@ alpha-mouse: Dapatkah Anda memberikan sedikit informasi tentang masalah yang Anda coba selesaikan? Ini akan membantu orang memberi Anda contoh yang relevan.
Jazza
@Jazza: Saya baru saja mengganti tag pertanyaan =) Saya bukan pertanyaan santosh
alpha-mouse
3
@TheMuffinMan benar, namun saya lebih suka cara hal-hal dijelaskan pada stackoverflow dibandingkan dengan MSDN terlalu kaku untuk cara formal menjelaskan kreasi mereka sendiri.
Sizons

Jawaban:

224

ObservableCollection adalah kumpulan yang memungkinkan kode di luar koleksi menjadi sadar ketika terjadi perubahan pada koleksi (tambah, pindahkan, hapus). Ini banyak digunakan dalam WPF dan Silverlight tetapi penggunaannya tidak terbatas di sana. Kode dapat menambahkan event handler untuk melihat kapan koleksi telah berubah dan kemudian bereaksi melalui event handler untuk melakukan beberapa pemrosesan tambahan. Ini mungkin mengubah UI atau melakukan operasi lain.

Kode di bawah ini tidak benar-benar melakukan apa-apa tetapi menunjukkan bagaimana Anda akan melampirkan handler di kelas dan kemudian menggunakan argumen acara untuk bereaksi dalam beberapa cara terhadap perubahan. WPF sudah memiliki banyak operasi seperti menyegarkan UI bawaan sehingga Anda mendapatkannya secara gratis saat menggunakan 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
        }
    }
}
Craig Suchanec
sumber
21
e.NewItems& e.OldsItemsmungkin nol tergantung pada tindakan. Mungkin melempar NullReferenceException.
dovid
7
sidenote: ketika Action adalah Move, elemen yang dipindahkan akan muncul di NewItems dan OldItems
bohdan_trotsenko
Terima kasih untuk ini:> WPF sudah memiliki banyak operasi seperti menyegarkan UI
bawaan
157

Suatu ObservableCollectionkarya pada dasarnya seperti kumpulan biasa kecuali bahwa ia mengimplementasikan antarmuka:

Karena itu sangat berguna ketika Anda ingin tahu kapan koleksi telah berubah. Suatu peristiwa dipicu yang akan memberi tahu pengguna entri apa yang telah ditambahkan / dihapus atau dipindahkan.

Lebih penting lagi mereka sangat berguna saat menggunakan penyatuan data pada formulir.

Liz
sumber
54

Dari Pro C # 5.0 dan .NET 4.5 Framework

The ObservableCollection<T>kelas sangat berguna dalam hal ini memiliki kemampuan untuk menginformasikan objek-objek eksternal ketika isinya telah berubah dalam beberapa cara (seperti yang Anda duga, bekerja dengan ReadOnlyObservableCollection<T>sangat mirip, tetapi hanya-baca di alam). Dalam banyak hal, bekerja dengan ObservableCollection<T>identik dengan bekerja dengan List<T>, mengingat bahwa kedua kelas ini mengimplementasikan antarmuka inti yang sama. Apa yang membuat ObservableCollection<T>kelas yang unik adalah bahwa kelas ini mendukung sebuah acara bernama CollectionChanged. Peristiwa ini akan memanas setiap kali item baru dimasukkan, item saat ini dihapus (atau dipindahkan), atau jika seluruh koleksi dimodifikasi. Seperti acara apa pun, CollectionChanged didefinisikan dalam hal delegasi, yang dalam hal ini adalah NotifyCollectionChangedEventHandler. Delegasi ini dapat memanggil metode apa pun yang mengambil objek sebagai parameter pertama, dan aNotifyCollectionChangedEventArgssebagai yang kedua. Pertimbangkan metode Main () berikut, yang mengisi koleksi yang dapat diobservasi yang berisi objek Person dan menghubungkan CollectionChangedperistiwa:

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

NotifyCollectionChangedEventArgsParameter yang masuk mendefinisikan dua properti penting, OldItemsdan NewItems, yang akan memberi Anda daftar item yang saat ini dalam koleksi sebelum acara dipecat, dan item baru yang terlibat dalam perubahan. Namun, Anda harus memeriksa daftar ini hanya dalam keadaan yang benar. Ingat bahwa acara CollectionChanged dapat diaktifkan saat item ditambahkan, dihapus, dipindahkan, atau diatur ulang. Untuk mengetahui tindakan mana yang memicu acara, Anda bisa menggunakan properti Action dari NotifyCollectionChangedEventArgs. Properti Action dapat diuji terhadap anggota NotifyCollectionChangedActionenumerasi berikut:

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

Anggota System.Collections.ObjectModel

Kata Roohullah Allem
sumber
1
apakah acara people_CollectionChanged akan menyala jika saya mengubah nama Orang di dalam koleksi (tanpa mengubah koleksi itu sendiri?)
BKSpurgeon
25

Penjelasan tanpa Kode

Bagi mereka yang menginginkan jawaban tanpa kode di belakangnya (boom-tish) saya akan angkat tangan:

Koleksi Normal - Tidak Ada Pemberitahuan

Sesekali saya pergi ke NYC dan istri saya meminta saya untuk membeli barang. Jadi saya membawa daftar belanjaan bersama saya. Daftar ini memiliki banyak hal di sana seperti:

  1. Tas tangan Louis Vuitton ($ 5000)
  2. Clive Christian's Imperial Majesty Perfume ($ 215.000)
  3. Gucci Sunglasses ($ 2000)

hahaha baik saya tidak membeli barang-barang itu. Jadi saya mencoretnya dan menghapusnya dari daftar dan saya menambahkan:

  1. 12 lusin bola golf Titleist.
  2. 12 lb bola bowling.

Jadi saya biasanya pulang tanpa barang dan dia tidak pernah senang. Masalahnya adalah dia tidak tahu tentang apa yang saya ambil dari daftar dan apa yang saya tambahkan ke dalamnya; dia tidak mendapat pemberitahuan.

ObservableCollection - notifikasi ketika perubahan dilakukan

Sekarang, setiap kali saya menghapus sesuatu dari daftar: dia mendapat pemberitahuan di teleponnya (yaitu sms / email dll)!

Koleksi yang dapat diamati bekerja dengan cara yang sama. Jika Anda menambah atau menghapus sesuatu ke atau dari itu: seseorang diberitahu. Dan ketika mereka diberitahu, maka mereka akan memanggil Anda dan Anda akan mendapatkan telinga penuh. Tentu saja konsekuensinya dapat disesuaikan melalui event handler.

Itu meringkas semuanya!

BKSpurgeon
sumber
7

Salah satu kegunaan terbesar adalah Anda dapat mengikat komponen UI menjadi satu, dan mereka akan merespons dengan tepat jika konten koleksi berubah. Misalnya, jika Anda mengikat ItemSource ListView ke satu, konten ListView akan secara otomatis diperbarui jika Anda memodifikasi koleksi.

EDIT: Ini beberapa contoh kode dari MSDN: http://msdn.microsoft.com/en-us/library/ms748365.aspx

Di C #, mengaitkan ListBox ke koleksi bisa semudah

listBox.ItemsSource = NameListData;

meskipun jika Anda belum mengaitkan daftar sebagai sumber daya statis dan mendefinisikan NameItemTemplate Anda mungkin ingin mengganti ToString PersonName (). Sebagai contoh:

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

itu adalah koleksi yang digunakan untuk memberi tahu sebagian besar UI untuk mengubah dalam koleksi, itu mendukung pemberitahuan otomatis.

Terutama digunakan dalam WPF,

Di mana misalkan Anda memiliki UI dengan kotak daftar dan menambahkan tombol dan ketika Anda mengklik tombol dia objek bertipe orang akan ditambahkan ke koleksi observasi dan Anda mengikat koleksi ini ke ItemSource dari Listbox, jadi segera setelah Anda menambahkan item baru dalam koleksi, Listbox akan memperbarui sendiri dan menambahkan satu item lagi di dalamnya.

TalentTuner
sumber
benarkah ini yang terjadi ?? : 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
sumber
dapatkah Anda menjelaskan mengapa FooObservableCollection menerapkan koleksi? Dan mengapa Anda memasukkan InsertItem?
Arie
@Rie: jujur, 8 tahun kemudian saya tidak ingat, jadi tidak tahu. Dari apa yang saya lihat di dokumen tidak perlu untuk semua ini, semuanya harus keluar dari kotak.
abatishchev