Silverlight2入門記4 - バインディング -

今回はバインディングについてです。
SilverlightバインディングをBinding式で行います。
{Binding xxx}のような形式で、具体的には

のように記述します。


コードビハインド側ではソース元であるDataContextプロパティを設定しています。
どこのオブジェクトをバインドするかをDataContextで指定するみたいです。

public Page()
{
InitializeComponent();
items.DataContext = AllBooks;
……
}

ちなみにAllBooksはObservableCollectionです。


バインディング式では、DataContextに設定されたオブジェクトのどのプロパティとバインドするかも記載できます。
下記のような感じ。


……

この例では先ほど設定したAllBooksの一つ一つのオブジェクト(Book)からTitleプロパティを抜き出して設定するわけです。


またバインディングには幾つかのモードがあります。

  • OneWay

コードビハインドからxamlの方向への更新のみです。
つまりC#側のプロパティが変われば反映はされるけど、XAML側で値を変えても
C#のプロパティは反映されません。

  • TwoWay

XAML側とコードビハインド側のどちらが更新されても反映される

  • OneTime

ワンタイムはOneWayの特殊例で、アプリケーションの起動時またはデータ コンテキストの変更時だけ更新されます。
その後はC#をなおしても反映されません。

  • デフォルト

TwoWayがデフォルトっぽい。


そのほかにもXAML側→C#側というOneWayToSourceってのも用意されているらしいんだけど
おいらが試している限りだとVSが怒る。Beta2でもしかしてなくなった?


で今回のソースコードは下記のような感じです。

<UserControl x:Class="FirstBinding.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:FirstBinding" 
    Width="400" Height="300">
    <UserControl.Resources>
        <local:CustomDateConverter x:Key="dateConverter" />
    </UserControl.Resources>
    <StackPanel Background="AliceBlue">
        <ListBox x:Name="items" ItemsSource="{Binding Mode=OneWay}" Margin="5" SelectionChanged="items_SelectionChanged">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Title}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <StackPanel>
            <Rectangle HorizontalAlignment="Left" Width="400" Height="2" Fill="Red" Margin="0,10,0,10" />
            <StackPanel x:Name="BookDetails">
                <TextBlock Text="{Binding Title, Mode=OneWay}" />
                <TextBlock Text="{Binding PublishedDate, Mode=OneWay, Converter={StaticResource dateConverter}}" />
            </StackPanel>
        </StackPanel>
    </StackPanel>
</UserControl>
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 System.Collections.ObjectModel;
using System.Windows.Data;

namespace FirstBinding
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            items.DataContext = AllBooks;
            AllBooks.Add(new Book("汁バラ教本2", new DateTime(2008, 1, 17)));
            AllBooks.Add(new Book("汁バラ教本特別編-もう一度最初から!-", new DateTime(2008, 6, 14)));
            items.SelectedIndex = 0;
        }

        private ObservableCollection<Book> AllBooksValue = null;

        public ObservableCollection<Book> AllBooks
        {
            get
            {
                if (AllBooksValue == null)
                {
                    AllBooksValue = new ObservableCollection<Book>();
                    AllBooksValue.Add(new Book("汁バラ教本1", new DateTime(2008, 7, 17)));
                }
                return AllBooksValue;
            }
        }

        private void items_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ListBox listBox = sender as ListBox;
            BookDetails.DataContext = AllBooks[listBox.SelectedIndex];
        }

    }

    public class Book
    {
        public string Title { get; set; }

        public DateTime PublishedDate { get; set; }

        public Book(string Title, DateTime PublishedDate)
        {
            this.Title = Title;
            this.PublishedDate = PublishedDate;
        }

        public override string ToString()
        {
            return Title + "(" + PublishedDate.ToLongDateString() + ")";
        }
    }

    //このPage専用のカスタムConverter。どうやら同じnamespace内に含めないと動かないみたい。
    public class CustomDateConverter : IValueConverter
    {
        #region IValueConverter メンバ

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            DateTime date = (DateTime)value;
            string s = date.Year.ToString() + "/" + date.Month.ToString();
            return s;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    
}

今回はSilverlight.netのソースを写経しました。


このまま次回はカスタムコンバータの作り方とかやります。