ObservableCollection ใน. net คืออะไร


227

ObservableCollection ใน. net คืออะไร


1
@ alpha-mouse: คุณช่วยให้ข้อมูลเพิ่มเติมเล็กน้อยเกี่ยวกับปัญหาที่คุณพยายามแก้ไขได้หรือไม่? สิ่งนี้จะช่วยให้ผู้คนให้ตัวอย่างที่เกี่ยวข้องแก่คุณ
Jazza

@Jazza: ฉันเพิ่งเปลี่ยนแท็กของคำถาม =) ฉันไม่ใช่คำถามของ santosh
alpha-mouse

3
@ TheMuffinMan จริง แต่ฉันชอบวิธีที่สิ่งต่าง ๆ ถูกอธิบายใน stackoverflow เมื่อเทียบกับ MSDN ที่เข้มงวดเกินไปกับวิธีที่เป็นทางการในการอธิบายการสร้างสรรค์ของพวกเขาเอง
Sizons

คำตอบ:


224

ObservableCollection เป็นคอลเล็กชันที่อนุญาตให้ใช้โค้ดภายนอกคอลเล็กชันที่ต้องระวังเมื่อมีการเปลี่ยนแปลงในคอลเลกชัน (เพิ่มย้ายลบออก) เกิดขึ้น มันถูกใช้อย่างมากใน WPF และ Silverlight แต่การใช้งานไม่ได้ จำกัด อยู่แค่นั้น รหัสสามารถเพิ่มตัวจัดการเหตุการณ์เพื่อดูว่าเมื่อใดคอลเลกชันที่มีการเปลี่ยนแปลงและตอบสนองผ่านตัวจัดการเหตุการณ์เพื่อทำการประมวลผลเพิ่มเติมบางอย่าง นี่อาจเป็นการเปลี่ยน UI หรือการดำเนินการอื่น ๆ

รหัสด้านล่างไม่ได้ทำอะไรเลยจริงๆ แต่แสดงให้เห็นว่าคุณแนบตัวจัดการในชั้นเรียนแล้วใช้เหตุการณ์ args เพื่อตอบสนองต่อการเปลี่ยนแปลง WPF มีการดำเนินการหลายอย่างเช่นการรีเฟรช UI ในตัวเพื่อให้คุณได้รับฟรีเมื่อใช้ 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
ด้านข้าง: เมื่อการกระทำคือการย้ายองค์ประกอบที่ย้ายจะปรากฏขึ้นในทั้ง NewItems และ OldItems
bohdan_trotsenko

ขอบคุณสำหรับสิ่งนี้:> WPF มีการดำเนินการหลายอย่างเช่นการรีเฟรช UI ในตัวเพื่อให้คุณใช้งานได้ฟรีเมื่อใช้ ObservableCollections
SlowLearner

157

ObservableCollectionทำงานเป็นหลักเช่นชุดปกติยกเว้นว่าจะดำเนินการเชื่อมต่อ:

เช่นนี้จะมีประโยชน์มากเมื่อคุณต้องการทราบเมื่อมีการเปลี่ยนแปลงคอลเลกชัน เหตุการณ์ถูกเรียกใช้ซึ่งจะบอกผู้ใช้ว่ามีการเพิ่ม / ลบหรือย้ายรายการใดบ้าง

ที่สำคัญพวกเขามีประโยชน์มากเมื่อใช้ databinding บนแบบฟอร์ม


54

จากPro C # 5.0 และ. NET Framework 4.5

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 สามารถเริ่มทำงานเมื่อมีการเพิ่มลบย้ายย้ายหรือรีเซ็ตรายการ ในการค้นหาว่าการกระทำใดที่ก่อให้เกิดเหตุการณ์คุณสามารถใช้คุณสมบัติการดำเนินการของ 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 ($ 5,000)
  2. น้ำหอมราชินีของ Clive Christian ($ 215,000)
  3. แว่นตากันแดด Gucci ($ 2,000)

ฮ่าฮ่าฮ่าดีฉันไม่ได้ซื้อสิ่งนั้นดังนั้นฉันจึงปิดพวกเขาและลบออกจากรายการและฉันเพิ่มแทน:

  1. ลูกกอล์ฟ Titleist 12 ลูก
  2. ลูกโบว์ลิ่ง 12 ปอนด์

ดังนั้นฉันมักจะกลับบ้านโดยไม่มีสินค้าและเธอไม่เคยพอใจ สิ่งหนึ่งคือเธอไม่รู้เกี่ยวกับสิ่งที่ฉันลบรายการและสิ่งที่ฉันเพิ่มลงในนั้น เธอไม่ได้รับการแจ้งเตือน

ObservableCollection - แจ้งเตือนเมื่อมีการเปลี่ยนแปลง

ตอนนี้เมื่อใดก็ตามที่ฉันลบบางสิ่งออกจากรายการ: เธอได้รับการแจ้งเตือนทางโทรศัพท์ (เช่น sms / อีเมล ฯลฯ )!

คอลเลกชันที่สังเกตได้ทำงานในลักษณะเดียวกัน หากคุณเพิ่มหรือลบบางสิ่งในหรือออกจาก: บางคนจะได้รับแจ้ง และเมื่อพวกเขาได้รับแจ้งแล้วพวกเขาก็โทรหาคุณและคุณจะได้รับเสียงเต็ม แน่นอนว่าผลที่ตามมาจะถูกปรับแต่งผ่านตัวจัดการเหตุการณ์

ผลรวมมันทั้งหมดขึ้น!


7

หนึ่งในการใช้งานที่ใหญ่ที่สุดคือคุณสามารถผูกส่วนประกอบ UI กับอุปกรณ์หนึ่งและจะตอบสนองอย่างเหมาะสมหากเนื้อหาของคอลเลกชันเปลี่ยนไป ตัวอย่างเช่นถ้าคุณผูกแหล่งข้อมูลของ ListView กับแหล่งหนึ่งเนื้อหาของ ListView จะอัปเดตโดยอัตโนมัติหากคุณแก้ไขคอลเลกชัน

แก้ไข: นี่คือตัวอย่างรหัสจาก MSDN: http://msdn.microsoft.com/en-us/library/ms748365.aspx

ใน C #, hooking กล่องรายการไปยังคอลเลกชันอาจเป็นเรื่องง่ายเหมือน

listBox.ItemsSource = NameListData;

แม้ว่าคุณจะไม่ได้เชื่อมโยงรายการเป็นทรัพยากรแบบคงที่และกำหนด NameItemTemplate ไว้คุณอาจต้องการแทนที่ ToString () ของ PersonName ตัวอย่างเช่น:

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

6

มันเป็นคอลเลกชันที่ใช้ในการแจ้งเตือน UI ส่วนใหญ่จะเปลี่ยนในคอลเลกชันมันรองรับการแจ้งเตือนอัตโนมัติ

ส่วนใหญ่ใช้ใน WPF

ถ้าสมมติว่าคุณมี UI พร้อมกล่องรายการและปุ่มเพิ่มและเมื่อคุณคลิกที่ปุ่มวัตถุประเภทบุคคลที่สมมติว่าจะถูกเพิ่มลงในการสังเกตการเก็บรวบรวมและคุณผูกคอลเลกชันนี้ไปยังแหล่งรายการของกล่องรายการทันทีที่คุณเพิ่ม รายการใหม่ในคอลเลกชันกล่องรายการจะอัปเดตตัวเองและเพิ่มอีกหนึ่งรายการในนั้น


สิ่งนี้เกิดขึ้นจริงหรือ : 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();
}

คุณช่วยอธิบายได้ไหมว่าทำไม FooObservableCollection นำคอลเล็กชั่นไปใช้? และทำไมคุณถึงแทรกรายการItem?
Arie

@Arie: สุจริต 8 ปีต่อมาฉันจำไม่ได้ดังนั้นไม่มีความคิด จากสิ่งที่ฉันเห็นในเอกสารไม่จำเป็นต้องมีสิ่งใดสิ่งนี้ทุกอย่างควรออกมาจากกล่อง
abatishchev
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.