2012年2月20日月曜日

データバインディングしている ListBox にアイテムを追加する

例えば、ListBox のバインディングソースとして、List<T> なオブジェクトを指定していると、 list.Add(hoge) のようなことをしても、それは ListBox に反映されません。
これを反映させるためには INotifyPropertyChanged を実装して、 PropertyChanged イベントを発生させる必要がありますが、 ObservableCollection<t> でくるむと簡単に実装することができることを id:ch3cooh393 さんのブログで知り、試しに作ってみました。
XAML
<phone:PhoneApplicationPage 
    x:Class="ListBoxTemplate1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
    
    <!-- テンプレート -->
    <phone:PhoneApplicationPage.Resources>
        <DataTemplate x:Key="ItemTemplate">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Path=Name}" Width="100" />
                <TextBlock Text="{Binding Path=Manufacturer}" />
            </StackPanel>
        </DataTemplate>
    </phone:PhoneApplicationPage.Resources>

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>


        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Button Content="Button" HorizontalAlignment="Left" Name="button1"
                    Click="button1_Click" VerticalAlignment="Top" />
            <Grid Margin="0,90,0,0">
                <ListBox Name="listBox1" ItemTemplate="{StaticResource ItemTemplate}"/>
            </Grid>
        </Grid>
    </Grid>
</phone:PhoneApplicationPage>
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace ListBoxTemplate1
{
    public partial class MainPage : PhoneApplicationPage
    {
        List<Car> carList;
        ObservableCollection<Car> ob;

        // コンストラクター
        public MainPage()
        {
            InitializeComponent();
            UpdateListBox();
        }

        private void UpdateListBox()
        {
            carList = new List();
            carList.Add(new Car("RX-7", "Mazda"));
            carList.Add(new Car("Stepwgn", "Honda"));
            carList.Add(new Car("Vitz", "Toyota"));

            ob = new ObservableCollection(carList);
            listBox1.ItemsSource = ob;

            // (*) このバインディングでは UI は更新されない
            //listBox1.ItemsSource = carList;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            ob.Add(new Car("Skyline", "Nissan"));
            ob[0].Name = "RX-8"; // これは UI に反映されない

            // (*)
            //carList.Add(new Car("Impreza", "Subaru"));
            //carList[0].Name = "Demio"
        }
    }

    public class Car
    {
        public string Name { get; set; }
        public string Manufacturer { get; set; }

        // コンストラクター
        public Car(string name, string manufcturer)
        {
            Name = name;
            Manufacturer = manufcturer;
        }
    }
}
"Button" を押した分だけ "Skyline" が追加されます。 しかし、Name の書き換えは動作しません。
これは INotifyPropertyChanged を実装するより仕方が無いようです。これは次回に。

0 件のコメント:

コメントを投稿