.netでのObservableCollectionの用途は何ですか?


227

.netでのObservableCollectionの用途は何ですか?


1
@ alpha-mouse:解決しようとしている問題についてもう少し詳しく教えてもらえますか?これは人々があなたに適切な例を与えるのを助けます。
Jazza

@ジャザ:私は質問のタグを変更しました=)私はサントシュの質問をしていません
alpha-mouse

3
@TheMuffinManは真実ですが、私は、MSDNが独自の作成を説明するための堅固すぎる形式的な方法と比較して、stackoverflowでの説明方法を好みます。
Sizons 2015

回答:


224

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
        }
    }
}

21
e.NewItemse.OldsItemsアクションによってはnullになる場合があります。投げるかもしれませんNullReferenceException
2015年

7
補足:アクションが移動の場合、移動した要素はNewItemsとOldItemsの両方に表示されます
bohdan_trotsenko

これをありがとう:> WPFには、UIの
更新

157

ObservableCollectionそれはインタフェースを実装していることを除いて、基本的に通常のコレクションのように動作します:

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

さらに重要なのは、フォームでデータバインディングを使用するときに非常に便利です。


54

プロのC#5.0と.NET 4.5 Frameworkの

このObservableCollection<T>クラスは、コンテンツが何らかの方法で変更されたときに外部オブジェクトに通知する機能を備えている点で非常に便利です(ご想像のとおり、操作 ReadOnlyObservableCollection<T>は非常に似ていますが、本質的に読み取り専用です)。多くの点で、2番目のとして使用します。次のMain()メソッドを考えます。これは、Personオブジェクトを含む監視可能なコレクションにデータを入力し、イベントを結び付けます 。ObservableCollection<T>同じですList<T>。これらのクラスの両方が同じコアインターフェースを実装していることを前提とします。何がObservableCollection<T>クラスがユニークなことは、このクラスは、名前付きイベントをサポートしていることですCollectionChanged。このイベントは、新しいアイテムが挿入されたとき、現在のアイテムが削除(または再配置)されるとき、またはコレクション全体が変更されたときに発生します。他のイベントと同様に、CollectionChangedはデリゲート(この場合は)に関して定義され NotifyCollectionChangedEventHandlerます。このデリゲートは、最初のパラメーターとしてオブジェクトを受け取る任意のメソッドを呼び出すことができ、NotifyCollectionChangedEventArgsCollectionChanged

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,
}

System.Collections.ObjectModelのメンバー


1
(コレクション自体を変更せずに)コレクション内のPersonの名前を変更すると、people_CollectionChangedイベントが発生します
BKSpurgeon

25

コードなしの説明

その背後にコードなしで回答を求めている人(ブームティッシュ)に手を上げます:

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

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

  1. Louis Vuittonハンドバッグ($ 5000)
  2. クライブクリスチャンの帝国陛下の香水($ 215,000)
  3. Gucciサングラス($ 2000)

ええと、私はそのようなものを購入していないので、それらを取り消してリストから削除し、代わりに追加します。

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

だから私は通常、商品なしで帰宅し、彼女は決して満足していません。問題は、私がリストから何を削除し、何を追加するかについて彼女が知らないことです。彼女は通知を受け取りません。

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

今、私がリストから何かを削除するときはいつでも:彼女は彼女の彼女の彼女の電話での通知(すなわち、SMS / Eメールなど)を受け取ります!

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

以上で合計です!


7

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

編集: 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);
}

6

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

主にWPFで使用され、

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


本当にこれが起こりますか?:O
キングス

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年後、私は覚えていません。私がドキュメントで見るものからこれは必要ありません、それはすべて箱から出すべきです。
abatishchev
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.