web-dev-qa-db-ja.com

.netでのObservableCollectionの使用とは何ですか?

.netでのObservableCollectionの使用とは何ですか?

210
santosh singh

ObservableCollectionは、コレクションの変更(追加、移動、削除)がいつ発生するかをコレクション外のコードが認識できるようにするコレクションです。 WPFおよびSilverlightで頻繁に使用されますが、使用はこれらに限定されません。コードは、イベントハンドラーを追加して、コレクションがいつ変更されたかを確認し、イベントハンドラーを介して反応して追加の処理を行うことができます。これは、UIの変更または他の操作の実行である可能性があります。

以下のコードは実際には何も行いませんが、クラスにハンドラーをアタッチし、イベント引数を使用して変更に何らかの方法で反応する方法を示しています。 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
        }
    }
}
207
Craig Suchanec

ObservableCollection は、インターフェースを実装することを除き、基本的に通常のコレクションと同様に機能します。

そのため、コレクションがいつ変更されたかを知りたい場合に非常に便利です。追加/削除または移動されたエントリをユーザーに通知するイベントがトリガーされます。

さらに重要なことは、フォームでデータバインディングを使用する場合に非常に役立つことです。

148
Liz

から Pro C#5.0および.NET 4.5 Framework

ObservableCollection<T>クラスは、内容が何らかの方法で変更されたときに外部オブジェクトに通知する機能を備えているという点で非常に便利です(ご想像のとおり、ReadOnlyObservableCollection<T>の操作は非常に似ていますが、本質的に読み取り専用です)。多くの点で、ObservableCollection<T>の操作はList<T>の操作と同じです。これらのクラスの両方が同じコアインターフェイスを実装していることを前提としています。 ObservableCollection<T>クラスをユニークにしているのは、このクラスがCollectionChangedという名前のイベントをサポートしていることです。このイベントは、新しいアイテムが挿入されたとき、現在のアイテムが削除(または再配置)されたとき、またはコレクション全体が変更されたときに発生します。他のイベントと同様に、CollectionChangedはデリゲートに関して定義されます。この場合はNotifyCollectionChangedEventHandlerです。このデリゲートは、オブジェクトを最初のパラメーターとして、NotifyCollectionChangedEventArgsを2番目のパラメーターとして取るメソッドを呼び出すことができます。次の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パラメーターは、2つの重要なプロパティ、OldItemsおよびNewItemsを定義します。これらは、イベントが発生する前に現在コレクションにあったアイテムのリストと、変更に関係した新しいアイテムを提供します。ただし、これらのリストは、正しい状況でのみ調査する必要があります。 CollectionChangedイベントは、アイテムが追加、削除、再配置、またはリセットされたときに発生する可能性があることを思い出してください。これらのアクションのどれがイベントをトリガーしたかを見つけるには、NotifyCollectionChangedEventArgsのActionプロパティを使用できます。 Actionプロパティは、NotifyCollectionChangedAction列挙型の次のメンバーのいずれかに対してテストできます。

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

Members of System.Collections.ObjectModel

49
Jahan

コードなしの説明

背後にコードのない答えが必要な場合(ブームっぽい)、私は手を挙げます:

通常のコレクション-通知なし

時々ニューヨークに行き、妻は物を買うように頼みます。だから私は買い物リストを持って行きます。リストには、次のような多くのものがあります。

  1. ルイ・ヴィトンのハンドバッグ(5000ドル)
  2. クライブクリスチャンの ’下香水(215,000ドル)
  3. グッチサングラス($ 2000)

ハハハ私はそのようなものを買っていません。だから私はそれらを消してリストから削除し、代わりに追加します:

  1. 12ダースのタイトリストゴルフボール。
  2. 12ポンドのボウリングボール。

だから私は通常、商品なしで家に帰りますが、彼女は決して喜んでいません。問題は、彼女が私がリストから外したものと私がリストに追加したものについて知らないことです。彼女は通知を受け取りません。

ObservableCollection-変更が行われたときの通知

今、リストから何かを削除するたびに:彼女は彼女の電話で通知を受け取ります(つまり、SMS /メールなど)

監視可能なコレクションはまったく同じように機能します。何かを追加または削除すると、誰かに通知されます。そして、彼らが通知されると、それから彼らはあなたに電話し、あなたは耳一杯になります。もちろん、結果はイベントハンドラーを介してカスタマイズできます。

それはすべてをまとめたものです!

19
BKSpurgeon

最大の用途の1つは、UIコンポーネントを1つにバインドでき、コレクションのコンテンツが変更された場合に適切に応答することです。たとえば、ListViewのItemsSourceをバインドすると、コレクションを変更するとListViewのコンテンツが自動的に更新されます。

EDIT:MSDNのサンプルコードは次のとおりです。 http://msdn.Microsoft.com/en-us/library/ms748365.aspx

C#では、ListBoxをコレクションにフックするのは簡単です。

listBox.ItemsSource = NameListData;

ただし、静的リソースとしてリストをフックしておらず、NameItemTemplateを定義していない場合は、PersonNameのToString()をオーバーライドできます。例えば:

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

コレクションの変更を主にUIに通知するために使用されるコレクションであり、自動通知をサポートします。

主にWPFで使用され、

リストボックスと追加ボタンを備えたUIがあり、ボタンをクリックすると、タイプのオブジェクトがobseravablecollectionに追加され、このコレクションをListboxのItemSourceにバインドすると仮定すると、コレクション内の新しいアイテム、Listboxはそれ自体を更新し、その中にもう1つのアイテムを追加します。

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