none
ObservableCollectionのバインドについて RRS feed

  • 質問

  • 同様のスレッドが存在したのですが、疑問点が少し違うので改めて質問させていただきます。

    現在、VS2013 C# でWPFアプリケーションを作成しております。

    そこで、ListBoxにバインドを行うのに下記のように実装しております。

    [xaml]

    <Window x:Class="CollectionBindingTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:CollectionBindingTest"
            Title="MainWindow"
            Width="525"
            Height="350">
        <Window.DataContext>
            <local:ListData />
        </Window.DataContext>
        <Grid x:Name="layoutRoot">
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <ListBox Grid.Row="0"
                     DisplayMemberPath="Name"
                     ItemsSource="{Binding Path=SampleDatas}" />
            <StackPanel Grid.Row="1">
                <Button Click="GetOnClick" Content="取得" />
                <Button Click="ClearOnClick" Content="初期化" />
            </StackPanel>
        </Grid>
    </Window>

    [xaml.cs]

    namespace CollectionBindingTest
    {
        public class SampleData
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
    
        public class ListData
        {
            public ObservableCollection<SampleData> SampleDatas { get; set; }
    
            public ListData()
            {
                this.SampleDatas = new ObservableCollection<SampleData>();
            }
        }
    
        public partial class MainWindow : Window
        {
            private ListData ListData
            {
                get { return this.DataContext as ListData; }
            }
    
            public MainWindow()
            {
                InitializeComponent();
            }
    
            /// <summary>
            /// データベースからデータの取得
            /// </summary>
            /// <returns></returns>
            private List<SampleData> GetSampleData()
            {
                var sampleDatas = new List<SampleData>
                {
                    new SampleData { Id = 1, Name = "taro" },
                    new SampleData { Id = 2, Name = "Jiro" },
                };
    
                return sampleDatas;
            }
    
            private void GetOnClick(object sender, RoutedEventArgs e)
            {
                // ケース1
                //this.ListData.SampleDatas = new ObservableCollection<SampleData>(this.GetSampleData());
    
                // ケース2
                this.ListData.SampleDatas.Clear();
                foreach (var sampleData in this.GetSampleData())
                {
                    this.ListData.SampleDatas.Add(sampleData);
                }
            }
    
            private void ClearOnClick(object sender, RoutedEventArgs e)
            {
                this.ListData.SampleDatas.Clear();
            }
        }
    }

    ケース1でListBoxに反映させたい場合は、ListDataクラスにINotifyPropertyChangedインターフェイスの実装が必要になるかと思います。(省略させていただきます。)

    アプリケーションの仕様上、ListBoxにデータを反映させる場合は必ずDBから最新の情報を取得して反映し、

    ユーザー操作等でCollectionに値を追加することはない場合、

    ListData.SampleDatasはObservableCollectionではなく、List<T>等のほうがいいのでしょうか?

    それともケース2のように毎回ループして追加すればいいのでしょうか?

    よろしくお願いいたします。

    • 編集済み れいじ 2015年10月8日 6:58
    2015年10月8日 6:56

回答

  • こんにちは。

    ObservableCollectionは要素の追加や削除が行われた時に変更通知をしてくれるリストです。
    その要件が必要でなければ、Listでも問題ないと思いますが。(ただしListに変更通知を発生させる必要はある)

    ケース2の場合だと、

    this.ListData.SampleDatas.Add(sampleData);

    の度に変更通知が発生しているので、
    実装方法によってはユーザインターフェイス上も1つづつ要素が追加されていくように見えると思います。

    View側にどう通知をしたいのかによって決めれば良いのではないでしょうか。
    2015年10月8日 7:08
    モデレータ
  • MainWindow <-- SampleDatasプロパティ <-- ObservableCollection
    か、
    MainWindow <-- SampleDatasプロパティ <-- List
    ということですが、まず両者の違いを正しく把握されていますか?

    MainWindowsにバインドしているリストに変化があったことを知らせるには、INotifyPropertyChangedインターフェースのPropertyChangedイベントで、SampleDatesプロパティに変化があったことを知らせることができます。
    しかし、このようなことをしなくても、ObservableCollectionはINotifyPropertyChangedインターフェースを実装していますから、ObservableCollectionに変化があれば、MainWindowsにその変化が伝わります。ここでいう変化はObservableCollectionのリストそのものの変化であり、リストの構成要素であるSampleDataの変化ではありません。SampleDataに変化があった場合にバインド先に伝えるには、SampleDataにもINotifyPropertyChangedインターフェースの実装が必要になります。

    一方、Listの方は、Listに変化があってもバインド先のMainWindowには伝わりません。よって、一番最初に書いたようにSampleDatesプロパティのPropertyChangedイベントを発生させる必要があります。

    今回の要件としては、データーベースから読んだものをバインドして終わりですから、ObservableCollectionでもListでも大差ありません。初回のバインドにはSampleDatesプロパティのPropertyChangedイベントを発生させる必要がありませんが、2回目以降のSampleDatesプロパティに再設定する際にはどちらの場合も必要です。


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答の候補に設定 星 睦美 2015年10月9日 1:26
    • 回答としてマーク れいじ 2015年10月9日 9:23
    2015年10月8日 8:01
    モデレータ

すべての返信

  • こんにちは。

    ObservableCollectionは要素の追加や削除が行われた時に変更通知をしてくれるリストです。
    その要件が必要でなければ、Listでも問題ないと思いますが。(ただしListに変更通知を発生させる必要はある)

    ケース2の場合だと、

    this.ListData.SampleDatas.Add(sampleData);

    の度に変更通知が発生しているので、
    実装方法によってはユーザインターフェイス上も1つづつ要素が追加されていくように見えると思います。

    View側にどう通知をしたいのかによって決めれば良いのではないでしょうか。
    2015年10月8日 7:08
    モデレータ
  • MainWindow <-- SampleDatasプロパティ <-- ObservableCollection
    か、
    MainWindow <-- SampleDatasプロパティ <-- List
    ということですが、まず両者の違いを正しく把握されていますか?

    MainWindowsにバインドしているリストに変化があったことを知らせるには、INotifyPropertyChangedインターフェースのPropertyChangedイベントで、SampleDatesプロパティに変化があったことを知らせることができます。
    しかし、このようなことをしなくても、ObservableCollectionはINotifyPropertyChangedインターフェースを実装していますから、ObservableCollectionに変化があれば、MainWindowsにその変化が伝わります。ここでいう変化はObservableCollectionのリストそのものの変化であり、リストの構成要素であるSampleDataの変化ではありません。SampleDataに変化があった場合にバインド先に伝えるには、SampleDataにもINotifyPropertyChangedインターフェースの実装が必要になります。

    一方、Listの方は、Listに変化があってもバインド先のMainWindowには伝わりません。よって、一番最初に書いたようにSampleDatesプロパティのPropertyChangedイベントを発生させる必要があります。

    今回の要件としては、データーベースから読んだものをバインドして終わりですから、ObservableCollectionでもListでも大差ありません。初回のバインドにはSampleDatesプロパティのPropertyChangedイベントを発生させる必要がありませんが、2回目以降のSampleDatesプロパティに再設定する際にはどちらの場合も必要です。


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答の候補に設定 星 睦美 2015年10月9日 1:26
    • 回答としてマーク れいじ 2015年10月9日 9:23
    2015年10月8日 8:01
    モデレータ
  • Tak1waさん

    返信ありがとうございます。

    今回の要件を考えると、Listでもよさそうなので、Listにします。

    ありがとうございました。

    2015年10月9日 1:13
  • trapemiyaさん

    返信ありがとうございます。

    今回疑問に思ったのは、ケース1の部分がtrapemiyaさんの仰る『ObservableCollectionのリストそのものの変化』にあたると思っていたのですが、違うということですね。

    2015年10月9日 1:25