WPFでコレクションをデータバインディングする

WPFのデータバインディング感覚が身につかなくて苦労しています。そんな中でこのサイトはとても参考になりました。

自分なりに落とすため、上記サイトを参考に分からない単語を調べながらコードを書いたら動きました。何となくわかった気になったので調べた事をメモします。

項目が追加または削除されたとき、あるいはリスト全体が更新されたときに通知を行う動的なデータ コレクションを表します。

つまり、ObservableCollectionを指定しておけば、C#内でプロパティソース値を変更したものがXAML上のターゲット値に反映されます。

このようにコレクションを指定します。<>内はコレクション内の要素の型になります。以下の例ではPersonクラスがコレクション内の要素になります。

private ObservableCollection<Person> people;

インスタンスを作成します。

this.people = new ObservableCollection<Person>

指定した型のコレクションに対する単純な反復処理をサポートする列挙子を公開します。コレクションのデータバインディングは、IEnumerableを実装していればどれでも対象になる。

項目が追加、削除された場合やリスト全体がクリアされた場合など、動的な変更をリスナーに通知します。IEnumerableインターフェースを実装し、さらにINotifyCollectionChangedインターフェースを実装しているコレクションは追加・削除などの変更操作をデータバインディングのターゲットと同期する事ができます。

複数のプロパティを共通のソースにバインドする場合は、DataContext プロパティを使用することをお勧めします。このプロパティは、データ バインドされたすべてのプロパティが共通のソースから継承するスコープを確立するための便利な方法を提供します。

今回の例ではMainWindowのDataContextにオブジェクトを設定しました。

       this.DataContext = people;

MainWindowから継承させず、直接ListbのDataContextに指定する事ができます。

            Listb.DataContext = people;

データバインドとはDataContext(に設定されたインスタンス)が保持する単一のプロパティへの参照を指定するものであり、DataContextに設定する事により、ターゲットに値を渡す事ができます。

ItemsControl のコンテンツの生成に使用するコレクションを取得または設定します。今回の場合、listboxのItemsSourceに直接コレクションを設定する事もできます。下の例では上記と同じ意味になります。

            Listb.ItemsSource = people;

ItemsSourceとは「複数の値をとりうるコントロールが持つ、選択肢一覧を保持する入れ物」です。ListBox、ComboBox、DataGridなど、内部に複数の値を保持するコントロールが持っているプロパティになります。

ItemsSourceにオブジェクトを設定すると、暗黙でターゲットとなるDataContextが変わります。

参考にした記事

        <ListBox x:Name="Listb"
            ItemsSource="{Binding}" Margin="0,0,0,49">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <TextBlock Text="{Binding Name}" />
                        <TextBlock Text="{Binding Age}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="61,279,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
        <Button x:Name="button1" Content="Button" HorizontalAlignment="Left" Margin="160,279,0,0" VerticalAlignment="Top" Width="75" Click="button1_Click"/>
    </Grid>

        private ObservableCollection<Person> people;
        public MainWindow()
        {
            InitializeComponent();
            // DataContextにPersonのコレクションを設定する
            this.people = new ObservableCollection<Person>(Enumerable.Range(1, 100)
                .Select(x => new Person
                {
                    Name = "tanaka" + x,
                    Age = (30 + x) % 50
                }));
            this.DataContext = people;
        }

        public class Person
        {
            public string Name
            {
                get;
                set;
            }

            public int Age
            {
                get;
                set;
            }
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            // コレクションに要素を追加する。
            this.people.Insert(0, new Person { Name = "追加したtanaka", Age = 100 });
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            // 全削除
            this.people.Clear();
        }

パラメーター
start
Type: System.Int32
シーケンス内の最初の整数の値。
count
Type: System.Int32
生成する連続した整数の数。
戻り値
Type: System.Collections.Generic.IEnumerable<Int32>
IEnumerable<Int32> C# の場合、または IEnumerable(Of Int32) で Visual Basic 連続した整数の範囲を格納しています。

例題のコード

            this.people = new ObservableCollection<Person>(Enumerable.Range(1, 100)
                .Select(x => new Person
                {
                    Name = "tanaka" + x,
                    Age = (30 + x) % 50
                }));

1-100までの連続した整数を発生させxに代入

30+xを50で割って余りがageに格納される