Việc sử dụng ObservableCollection trong .net là gì?


227

Việc sử dụng ObservableCollection trong .net là gì?


1
@ alpha-mouse: Bạn có thể cung cấp thêm một chút thông tin về vấn đề bạn đang cố gắng giải quyết không? Điều này sẽ giúp mọi người cho bạn ví dụ liên quan.
Jazza

@Jazza: Tôi vừa thay đổi thẻ câu hỏi =) Tôi không phải câu hỏi của tôi
chuột alpha

3
@TheMuffinMan đúng, nhưng tôi thích cách mọi thứ được giải thích trên stackoverflow so với MSDN quá cứng nhắc với cách giải thích chính thức về sáng tạo của họ.
Sizons

Câu trả lời:


224

ObservableCollection là một bộ sưu tập cho phép mã bên ngoài bộ sưu tập nhận biết khi có thay đổi đối với bộ sưu tập (thêm, di chuyển, xóa). Nó được sử dụng rất nhiều trong WPF và Silverlight nhưng việc sử dụng nó không giới hạn ở đó. Mã có thể thêm các trình xử lý sự kiện để xem khi nào bộ sưu tập đã thay đổi và sau đó phản ứng thông qua trình xử lý sự kiện để thực hiện một số xử lý bổ sung. Điều này có thể thay đổi UI hoặc thực hiện một số thao tác khác.

Mã dưới đây không thực sự làm gì cả nhưng chứng minh cách bạn đính kèm một trình xử lý trong một lớp và sau đó sử dụng sự kiện lập luận để phản ứng theo cách nào đó với các thay đổi. WPF đã có nhiều hoạt động như làm mới UI được tích hợp sẵn để bạn có được chúng miễn phí khi sử dụng 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.OldsItemscó thể là null tùy thuộc vào hành động. Nó có thể ném NullReferenceException.
dovid

7
sidenote: khi Action is Move, phần tử được di chuyển sẽ xuất hiện trong cả NewItems và OldItems
bohdan_trotsenko 14/03/2015

Cảm ơn bạn vì điều này:> WPF đã có nhiều hoạt động như làm mới UI được tích hợp sẵn để bạn có được chúng miễn phí khi sử dụng ObservableCollections
SlowLearner

157

Một ObservableCollectiontác phẩm về cơ bản giống như một bộ sưu tập thông thường ngoại trừ việc nó thực hiện các giao diện:

Vì vậy, nó rất hữu ích khi bạn muốn biết khi nào bộ sưu tập đã thay đổi. Một sự kiện được kích hoạt sẽ cho người dùng biết những mục đã được thêm / xóa hoặc di chuyển.

Quan trọng hơn, chúng rất hữu ích khi sử dụng cơ sở dữ liệu trên một biểu mẫu.


54

Từ Pro C # 5.0 và .NET 4.5 Framework

Các ObservableCollection<T>lớp học là rất hữu ích ở chỗ nó có khả năng thông báo cho đối tượng bên ngoài khi nội dung của nó đã thay đổi một cách nào đó (như bạn có thể đoán, làm việc với ReadOnlyObservableCollection<T>rất giống, nhưng chỉ đọc trong tự nhiên). Theo nhiều cách, làm việc với cái ObservableCollection<T>giống hệt như làm việc với List<T>, với điều kiện là cả hai lớp này đều thực hiện cùng một giao diện cốt lõi. Điều làm cho ObservableCollection<T>lớp duy nhất là lớp này hỗ trợ một sự kiện có tên CollectionChanged. Sự kiện này sẽ kích hoạt bất cứ khi nào một mục mới được chèn, một mục hiện tại bị xóa (hoặc di dời) hoặc nếu toàn bộ bộ sưu tập được sửa đổi. Giống như bất kỳ sự kiện nào, CollectionChanged được định nghĩa theo nghĩa của một đại biểu, trong trường hợp này là NotifyCollectionChangedEventHandler. Đại biểu này có thể gọi bất kỳ phương thức nào lấy một đối tượng làm tham số đầu tiên vàNotifyCollectionChangedEventArgsnhư là thứ hai. Hãy xem xét phương thức Main () sau đây, tập hợp một bộ sưu tập có thể quan sát có chứa các đối tượng Person và nối kết CollectionChangedsự kiệ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());
            }
        }
   }
}

NotifyCollectionChangedEventArgsTham số đến xác định hai thuộc tính quan trọng OldItemsNewItemssẽ cung cấp cho bạn danh sách các mục hiện có trong bộ sưu tập trước khi sự kiện diễn ra và các mục mới có liên quan đến thay đổi. Tuy nhiên, bạn sẽ muốn kiểm tra các danh sách này chỉ trong các trường hợp chính xác. Hãy nhớ lại rằng sự kiện CollectionChanged có thể kích hoạt khi các mục được thêm, xóa, di chuyển hoặc đặt lại. Để khám phá hành động nào trong số những hành động này đã kích hoạt sự kiện, bạn có thể sử dụng thuộc tính Hành động của NotifyCollectionChangedEventArss. Thuộc tính Hành động có thể được kiểm tra đối với bất kỳ thành viên nào sau đây của NotifyCollectionChangedActionbảng liệt kê:

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

Thành viên của System.Collections.ObjectModel


1
sự kiện People_CollectionChanged sẽ kích hoạt nếu tôi thay đổi tên của một người trong bộ sưu tập (mà không thay đổi chính bộ sưu tập đó?)
BKSpurgeon

25

Giải thích không có Mã

Đối với những người muốn có câu trả lời mà không có bất kỳ mã nào đằng sau nó (boom-tish) tôi sẽ giơ tay:

Bộ sưu tập bình thường - Không có thông báo

Thỉnh thoảng tôi đến NYC và vợ yêu cầu tôi mua đồ. Vì vậy, tôi có một danh sách mua sắm với tôi. Danh sách này có rất nhiều thứ như:

  1. Túi xách Louis Vuitton ($ 5000)
  2. Nước hoa Hoàng gia Clive Christian ($ 215.000)
  3. Kính râm Gucci ($ 2000)

hahaha tốt, tôi không mua thứ đó. Vì vậy, tôi gạch bỏ chúng và xóa chúng khỏi danh sách và thay vào đó tôi thêm vào:

  1. 12 tá bóng golf Titleist.
  2. Quả bóng bowling 12 lb.

Vì vậy, tôi thường về nhà mà không có hàng hóa và cô ấy không bao giờ hài lòng. Vấn đề là cô ấy không biết về những gì tôi đưa ra khỏi danh sách và những gì tôi thêm vào đó; cô ấy không nhận được thông báo.

ObservableCollection - thông báo khi có thay đổi

Bây giờ, bất cứ khi nào tôi xóa một cái gì đó khỏi danh sách: cô ấy nhận được thông báo trên điện thoại của mình (ví dụ: sms / email, v.v.)!

Bộ sưu tập quan sát hoạt động theo cùng một cách. Nếu bạn thêm hoặc xóa một cái gì đó đến hoặc từ nó: ai đó được thông báo. Và khi họ được thông báo, sau đó họ gọi cho bạn và bạn sẽ nhận được một tai. Tất nhiên hậu quả là tùy biến thông qua xử lý sự kiện.

Đó là tất cả lên!


7

Một trong những ứng dụng lớn nhất là bạn có thể liên kết các thành phần UI với một và chúng sẽ phản hồi phù hợp nếu nội dung của bộ sưu tập thay đổi. Ví dụ: nếu bạn liên kết ItemSource của ListView với một, nội dung của ListView sẽ tự động cập nhật nếu bạn sửa đổi bộ sưu tập.

EDIT: Đây là một số mã mẫu từ MSDN: http://msdn.microsoft.com/en-us/l Library / ms748365.aspx

Trong C #, việc nối ListBox vào bộ sưu tập có thể dễ dàng như

listBox.ItemsSource = NameListData;

mặc dù nếu bạn chưa nối danh sách dưới dạng tài nguyên tĩnh và NameItemTemplate được xác định, bạn có thể muốn ghi đè ToString () của PersonName. Ví dụ:

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

6

nó là một bộ sưu tập được sử dụng để thông báo cho hầu hết UI để thay đổi trong bộ sưu tập, nó hỗ trợ thông báo tự động.

Chủ yếu được sử dụng trong WPF,

Trường hợp giả sử bạn có UI với hộp danh sách và thêm nút và khi bạn nhấp vào nút anh ta, một đối tượng thuộc loại người giả sử sẽ được thêm vào bộ quan sát và bạn liên kết bộ sưu tập này với ItemSource của Listbox, vì vậy ngay khi bạn thêm mục mới trong bộ sưu tập, Listbox sẽ tự cập nhật và thêm một mục nữa trong đó.


thực sự điều này xảy ra ?? : 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();
}

bạn có thể giải thích tại sao FooObservableCollection thực hiện bộ sưu tập không? Và tại sao bạn lại rụng trứng?
Arie

@Arie: Thành thật mà nói, 8 năm sau tôi không nhớ, nên không biết. Từ những gì tôi thấy trong các tài liệu , không cần bất kỳ thứ gì trong số này, tất cả sẽ ra khỏi hộp.
abatishchev
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.