.Net में ऑब्ज़र्वेबलकोलेक्शन का उपयोग क्या है?


227

.Net में ऑब्ज़र्वेबलकोलेक्शन का उपयोग क्या है?


1
@ अल्फा-माउस: क्या आप उस समस्या के बारे में थोड़ी और जानकारी दे सकते हैं जिसे आप हल करने की कोशिश कर रहे हैं? यह लोगों को आपको प्रासंगिक उदाहरण देने में मदद करेगा।
जज़्ज़ा 25:10

@ झाझा: मैंने सिर्फ सवाल के टैग बदल दिए हैं =) मैं संतोष का सवाल नहीं पूछूंगा
अल्फा-माउस

3
@ TheMuffinMan सच है, फिर भी मैं पसंद करता हूं कि एमएसडीएन की तुलना में स्टैकओवरफ्लो पर चीजों को समझाया जाता है, अपनी खुद की रचनाओं को समझाने के औपचारिक तरीके से भी।
सिजन्स

जवाबों:


224

ओब्जर्वेबल कॉलेक्शन एक संग्रह है जो संग्रह के बाहर कोड की जानकारी देता है जब संग्रह में परिवर्तन होता है (ऐड, मूव, रिमूव)। यह WPF और सिल्वरलाइट में भारी उपयोग किया जाता है, लेकिन इसका उपयोग वहाँ तक सीमित नहीं है। कोड ईवेंट हैंडलर्स को यह देखने के लिए जोड़ सकता है कि संग्रह कब बदल गया है और फिर कुछ अतिरिक्त प्रसंस्करण करने के लिए ईवेंट हैंडलर के माध्यम से प्रतिक्रिया करें। यह यूआई को बदल सकता है या कुछ अन्य ऑपरेशन कर सकता है।

नीचे दिया गया कोड वास्तव में कुछ भी नहीं करता है, लेकिन यह दर्शाता है कि आप किसी कक्षा में एक हैंडलर को कैसे संलग्न करेंगे और फिर परिवर्तनों के लिए किसी तरह से प्रतिक्रिया करने के लिए घटना आर्ग का उपयोग करें। WPF में पहले से ही बहुत सारे ऑपरेशन हैं जैसे कि UI में निर्मित रीफ्रेश करना ताकि आप उन्हें ऑब्जर्वेबल कॉलेक्शन का उपयोग करते समय मुफ्त में प्राप्त कर सकें

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 निर्मित रीफ्रेश करना, ताकि आप उन्हें अवलोकन के दौरान मुफ्त में प्राप्त कर सकें
SlowLearner

157

एक ObservableCollectionको छोड़कर यह इंटरफेस को लागू करता है कि एक नियमित संग्रह की तरह अनिवार्य रूप से काम करता है:

जैसे कि यह बहुत उपयोगी है जब आप जानना चाहते हैं कि संग्रह कब बदल गया है। एक घटना शुरू हो जाती है जो उपयोगकर्ता को बताएगी कि प्रविष्टियों को क्या जोड़ा / हटाया या स्थानांतरित किया गया है।

एक फॉर्म पर डेटाबाइंडिंग का उपयोग करते समय अधिक महत्वपूर्ण रूप से वे बहुत उपयोगी होते हैं।


54

से प्रो सी # 5.0 और .NET 4.5 फ़्रेमवर्क

यह ObservableCollection<T>वर्ग बहुत उपयोगी है कि इसमें बाहरी वस्तुओं को सूचित करने की क्षमता है जब इसकी सामग्री किसी तरह से बदल गई है (जैसा कि आप अनुमान लगा सकते हैं, इसके साथ काम करना ReadOnlyObservableCollection<T>बहुत समान है, लेकिन केवल-पढ़ने के लिए प्रकृति में है)। कई मायनों में, के साथ काम करना ObservableCollection<T>समान है List<T>, यह देखते हुए कि ये दोनों वर्ग एक ही मूल इंटरफेस को लागू करते हैं। ObservableCollection<T>कक्षा को जो विशिष्ट बनाता है वह यह है कि यह वर्ग नाम की एक घटना का समर्थन करता है CollectionChanged। जब भी कोई नया आइटम डाला जाता है, तो एक चालू आइटम हटा दिया जाता है (या स्थानांतरित किया जाता है), या यदि पूरे संग्रह को संशोधित किया जाता है, तो यह घटना आग लग जाएगी। किसी भी घटना की तरह, CollectionChanged को एक प्रतिनिधि के रूप में परिभाषित किया गया है, जो इस मामले में है NotifyCollectionChangedEventHandler । यह प्रतिनिधि किसी भी विधि को कह सकता है जो पहले पैरामीटर के रूप में एक वस्तु लेता है, और एNotifyCollectionChangedEventArgsदूसरे के रूप में। निम्नलिखित मुख्य () विधि पर विचार करें, जो व्यक्तिगत वस्तुओं और 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, जो आपको उन वस्तुओं की एक सूची देगा जो वर्तमान में घटना से पहले संग्रह में थे, और नए आइटम जो परिवर्तन में शामिल थे। हालाँकि, आप इन सूचियों की जाँच सही परिस्थितियों में ही करना चाहेंगे। याद रखें कि जब आइटम जोड़े, हटाए गए, स्थानांतरित किए गए या रीसेट किए गए हैं, तो संग्रहित ईवेंट आग लगा सकता है। यह पता लगाने के लिए कि इनमें से किस क्रिया ने ईवेंट को ट्रिगर किया है, आप NotifyCollectionChangedEventAggs की एक्शन प्रॉपर्टी का उपयोग कर सकते हैं। एक्शन संपत्ति को NotifyCollectionChangedActionगणना के निम्नलिखित सदस्यों में से किसी के खिलाफ परीक्षण किया जा सकता है :

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

System.Collections.ObjectModel के सदस्य


1
people_CollectionChanged घटना आग अगर मैं एक व्यक्ति के नाम पर वसूली में (संग्रह खुद को बदले बिना?) बदल जाएगा
BKSpurgeon

25

कोड के बिना स्पष्टीकरण

उन लोगों के लिए जो बिना किसी कोड के उत्तर चाहते हैं (बूम-टीश) मैं अपना हाथ ऊपर कर दूंगा:

सामान्य संग्रह - कोई सूचना नहीं

अब मैं NYC में जाता हूं और मेरी पत्नी मुझसे सामान खरीदने के लिए कहती है। इसलिए मैं अपने साथ एक शॉपिंग लिस्ट लेकर जाता हूं। सूची में बहुत सारी चीजें हैं जैसे:

  1. लुई वुइटन हैंडबैग ($ 5000)
  2. क्लाइव क्रिश्चियन की शाही महिमा इत्र ($ 215,000)
  3. गुच्ची धूप का चश्मा ($ 2000)

हाहा मैं अच्छी तरह से उस सामान को नहीं खरीद रहा हूँ। इसलिए मैं उन्हें पार करता हूँ और उन्हें सूची से हटा देता हूँ और इसके बजाय जोड़ देता हूँ:

  1. 12 दर्जन टाइटलिस्ट गोल्फ की गेंद।
  2. 12 lb बॉलिंग बॉल।

इसलिए मैं आमतौर पर सामान के बिना घर आता हूं और वह कभी प्रसन्न नहीं होती है। बात यह है कि वह इस बारे में नहीं जानती कि मैं सूची से क्या निकालता हूं और इस पर क्या जोड़ता हूं; उसे कोई सूचना नहीं मिलती है।

ऑब्ज़र्वेबल कॉलेक्शन - नोटिफिकेशन जब किए गए बदलाव

अब, जब भी मैं सूची से कुछ निकालता हूं: उसे अपने फोन पर एक सूचना मिलती है (जैसे एसएमएस / ईमेल आदि)!

अवलोकनीय संग्रह उसी तरह काम करता है। यदि आप इसमें या इससे कुछ जोड़ते या हटाते हैं: किसी को सूचित किया जाता है। और जब उन्हें सूचित किया जाता है, ठीक है, तब वे आपको फोन करते हैं और आपको एक कान भरा हुआ मिलेगा। बेशक परिणाम घटना हैंडलर के माध्यम से अनुकूलन योग्य हैं।

कि यह सब ऊपर sums!


7

सबसे बड़े उपयोगों में से एक यह है कि आप यूआई घटकों को एक से बांध सकते हैं, और वे संग्रह की सामग्री को बदलने पर उचित जवाब देंगे। उदाहरण के लिए, यदि आप किसी एक को ListView के ItemSource से बाँधते हैं, तो यदि आप संग्रह को संशोधित करते हैं तो ListView की सामग्री स्वचालित रूप से अपडेट हो जाएगी।

संपादित करें: यहाँ MSDN से कुछ नमूना कोड हैं: http://msdn.microsoft.com/en-us/library/ms748365.aspx

C # में, ListBox को संग्रह में हुक करना जितना आसान हो सकता है

listBox.ItemsSource = NameListData;

हालाँकि यदि आपने सूची को स्थैतिक संसाधन के रूप में शामिल नहीं किया है और NameItemTemplate को परिभाषित किया है तो आप पर्सननेम की ToString () को ओवरराइड कर सकते हैं। उदाहरण के लिए:

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

6

यह एक संग्रह है जो संग्रह में बदलने के लिए ज्यादातर यूआई को सूचित करने के लिए उपयोग किया जाता है, यह स्वचालित अधिसूचना का समर्थन करता है।

मुख्य रूप से WPF में उपयोग किया जाता है,

मान लीजिए कि आपके पास एक सूची बॉक्स के साथ UI है और बटन जोड़ें और जब आप बटन पर क्लिक करते हैं, तो उस प्रकार के मान वाले व्यक्ति को ऑब्ज़र्वरएबलेक्लेओन में जोड़ा जाएगा और आप इस संग्रह को सूची बॉक्स के आइटम स्रोत में बाँध देते हैं, इसलिए जैसे ही आपने एक जोड़ा संग्रह में नया आइटम, लिस्टबॉक्स खुद को अपडेट करेगा और इसमें एक और आइटम जोड़ देगा।


वास्तव में ऐसा होता है ?? : ओ
किंग्स

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

@Arie: ईमानदारी से, 8 साल बाद मुझे याद नहीं है, इसलिए कोई विचार नहीं है। डॉक्स में जो मैं देख रहा हूं , उसमें से किसी की भी जरूरत नहीं है, यह सब बॉक्स से बाहर आना चाहिए।
अबिशशेव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.