Silverlight ベースのアプリケーションの多くは、データをコントロール内に表示します。データは多くの場合、株式相場、ヘッドライン、イメージなどのビジネス オブジェクトまたはビジネス オブジェクトのコレクションです。また、ユーザーが選択したリスト項目の詳細をテキスト ボックスなどの別のコントロールに表示させたい場合もよくあります。このクイックスタートでは、コントロールを単一の項目にバインドする方法と、リスト コントロールを項目のコレクションにバインドする方法について説明します。さらに、コントロール項目の表示のカスタマイズ方法や、選択項目に応じた詳細ビューを実装する方法、データを表示用に変換する方法についても説明します。
このクイックスタートは、次のセクションで構成されています。
バインドの詳細については、MSDN の Silverlight ドキュメントの「データ バインディング」を参照してください。
Silverlight で使用できるコントロールの詳細については、MSDN の Silverlight ドキュメントの「制御」を参照してください。
単一項目へのコントロールのバインド
データ バインディングはターゲットとソースで構成されます。通常、バインドのターゲットはコントロール プロパティです。この場合のターゲットは、DependencyProperty になります。
コントロールを単一の項目にバインドする例を次に示します。ターゲットは、テキスト ボックス コントロールの Text プロパティです。ソースは、シンプルな楽曲データの Recording クラスです。
XAML
<Grid x:Name="LayoutRoot" Background="White" HorizontalAlignment="Center" > <TextBox VerticalAlignment="Top" IsReadOnly="True" Margin="5" TextWrapping="Wrap" Height="50" Width="200" Text="{Binding Mode=OneWay}" x:Name="textBox1"/> </Grid>
C#
// A simple business object public class Recording { public Recording() { }
public Recording(string artistName, string cdName, DateTime release) { Artist = artistName; Name = cdName; ReleaseDate = release; }
public string Artist { get; set; } public string Name { get; set; } public DateTime ReleaseDate { get; set; }
// Override the ToString method. public override string ToString() { return Name + " by " + Artist + ", Released: " + ReleaseDate.ToShortDateString(); }
}
...
// Set the data context to a new Recording. textBox1.DataContext = new Recording("Chris Sells", "Chris Sells Live", new DateTime(2008, 2, 5));
Visual Basic
Public Class Recording
Public Sub New() End Sub
Public Sub New(ByVal artistName As String, ByVal cdName As String, _ ByVal release As DateTime)
Artist = artistName Name = cdName ReleaseDate = release End Sub
Private artistValue As String Private nameValue As String Private releaseDateValue As DateTime
Public Property Artist() As String Get Return artistValue End Get Set(ByVal value As String) artistValue = value End Set End Property
Public Property Name() As String Get Return nameValue End Get Set(ByVal value As String) nameValue = value End Set End Property
Public Property ReleaseDate() As DateTime Get Return releaseDateValue End Get Set(ByVal value As DateTime) releaseDateValue = value End Set End Property
' Override ToString. Public Overloads Overrides Function ToString() As String Return Name + " by " + Artist + ", Released: " + releaseDate.ToShortDateString() End Function End Class
...
' Set the data context to a new recording. textBox1.DataContext = New Recording("Chris Sells", "Chris Sells Live", _ New DateTime(2008, 2, 5))
楽曲情報をテキスト ボックスに表示するには、マークアップ拡張機能を使用してコントロールの Text プロパティを Binding に設定します。この例では、モードを BindingMode.OneWay に設定しています。このモードではソースからデータを取得しますが、変更内容はソースに反映されません。マークアップ拡張機能とその構文の詳細については、MSDN の Silverlight ドキュメントの「Binding のマークアップ拡張機能」を参照してください。
Recording クラスには、3 つのパブリック プロパティと ToString メソッドのオーバーライドがあります。プロパティは、Artist、Name、および ReleaseDate です。ToString メソッドは、書式が指定されていない場合に呼び出されて、バインドされているオブジェクトを表示する重要な機能です。バインドにあたって Binding.Source プロパティは直接設定していません。代わりに、TextBox コントロールの FrameworkElement.DataContext プロパティに新しい Recording オブジェクトを設定しています。
オブジェクトのコレクションへのコントロールのバインド
前の例では、データをコントロールにバインドする構文を示しましたが、これはあまり実用的ではありません。より一般的なシナリオとして、ビジネス オブジェクトのコレクションへのバインドがあります。コレクションへのデータ バインディングには、ObservableCollection ジェネリック クラスが適しています。INotifyPropertyChanged および INotifyCollectionChanged インターフェイスが実装されていることがその理由です。これらのインターフェイスは、リスト内の項目またはリスト自体のプロパティが変更された場合に、バインドされているコントロールに変更を通知します。コレクションのオブジェクトのプロパティの変更内容を使用して、バインドされているコントロールを更新する場合は、ビジネス オブジェクトも INotifyPropertyChanged を実装している必要があります。
次の例では、楽曲の Recording オブジェクトのコレクションを ComboBox にバインドしています。このサンプルを実行するには、コンボ ボックスにある下向き矢印をクリックします。バインドされている楽曲のリストが表示されます。
XAML
<StackPanel x:Name="LayoutRoot" Background="White"> <ComboBox x:Name="ComboBox1" Margin="5" Height="40" Width="300" ItemsSource="{Binding Mode=OneWay}" /> </StackPanel>
C#
public ObservableCollection<Recording> MyMusic = new ObservableCollection<Recording>();
public Page() { InitializeComponent();
// Add items to the collection. MyMusic.Add(new Recording("Chris Sells", "Chris Sells Live", new DateTime(2008, 2, 5))); MyMusic.Add(new Recording("Luka Abrus", "The Road to Redmond", new DateTime(2007, 4, 3))); MyMusic.Add(new Recording("Jim Hance", "The Best of Jim Hance", new DateTime(2007, 2, 6)));
// Set the data context for the combo box. ComboBox1.DataContext = MyMusic; }
Visual Basic
Public MyMusic As New ObservableCollection(Of Recording)()
Public Sub New() InitializeComponent() ' Add items to the collection. MyMusic.Add(New Recording("Chris Sells", "Chris Sells Live", _ New DateTime(2008, 2, 5))) MyMusic.Add(New Recording("Luka Abrus", "The Road to Redmond", _ New DateTime(2007, 4, 3))) MyMusic.Add(New Recording("Jim Hance", "The Best of Jim Hance", _ New DateTime(2007, 2, 6)))
' Set the data context for the combo box. ComboWithTemplate.DataContext = MyMusic End Sub
楽曲を ComboBox に表示するには、このコントロールの ItemsControl.ItemsSource プロパティに Binding を設定し、ComboBox コントロールの FrameworkElement.DataContext プロパティに Recording オブジェクトのコレクションを設定して、バインド用のソースを取得します。ComboBoxItem は、コレクションのアイテムごとに作成されます。ToString が Recording オブジェクトごとに自動的に呼び出され、オブジェクトの内容がコンボ ボックス項目に表示されます。
データ テンプレートによるコントロールへの項目の表示
項目を表示するには、リストの項目の ToString メソッドを使用できますが、一般的には DataTemplate を使用して、データがバインドされている項目の表示をカスタマイズします。DataTemplate を使用すると、リスト項目がコントロールにどのように表示されるかをカスタマイズできます。通常、データ テンプレートを設定するには、コンテンツ コントロールの ContentControl.ContentTemplate プロパティ、または項目コントロールの ItemsControl.ItemTemplate プロパティを使用します。
次の例は、データ テンプレートを使用してコンボ ボックスにバインドした音楽 CD のリストです。コンボ ボックスは ItemsControl であるため、ItemTemplate プロパティにデータ テンプレートを設定して、各項目のデータ テンプレートを作成します。このサンプルを実行するには、下向き矢印をクリックしてください。音楽 CD のリストが表示されます。前のサンプルとは表示内容が異なり、アーティスト名と CD タイトルがカスタム形式で表示されます。
XAML
<ComboBox x:Name="ComboWithTemplate" Margin="5" Width="400" HorizontalAlignment="Left" ItemsSource="{Binding Mode=OneWay}" > <ComboBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Margin="2"> <TextBlock Text="Artist:" Margin="2" /> <TextBlock Text="{Binding Artist}" Margin="2" /> <TextBlock Text="CD Name:" Margin="10,2,0,2" /> <TextBlock Text="{Binding Name}" Margin="2" /> </StackPanel> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>
XAML にデータ テンプレートが定義されているのが確認できます。データ テンプレートには、4 つの TextBlock コントロールを持つ StackPanel が含まれます。このスタック パネルは水平方向に設定されているため、4 つのテキスト ブロック コントロールは横に並んで表示されます。この内、2 つの TextBlock コントロールは、Recording オブジェクトの Artist プロパティおよび Name プロパティにバインドされています。残りの 2 つの TextBlock コントロールは静的テキストを表示します。バインドによって、バインドされた各項目に Recording オブジェクトのプロパティへのパスが提供されます。前の例と同様に、このバインドは、音楽 CD リストに設定されるデータ コンテキストによって異なります。
この XAML では、プロパティ要素構文を使用しています。XAML の構文の詳細については、MSDN の Silverlight ドキュメントの「XAML の概要」を参照してください。コントロール レイアウトの詳細については、MSDN の Silverlight ドキュメントの「オブジェクトの配置とレイアウト」を参照してください。
詳細ビューの追加
選択されたコレクション内の項目の詳細を表示するには、適切な UI を作成して、表示したいデータにバインドする必要があります。これを実行するには、バインド用のデータ コンテキストを、コレクション全体ではなくコレクション内の項目に設定します。また、選択項目が変更された場合、そのデータ コンテキストを更新する必要があります。
次の例は、データ テンプレートを使用してコンボ ボックスにバインドした音楽 CD のリストです。ただし、この例では詳細ビューが追加されています。このサンプルを実行するには、下向き矢印をクリックして CD を選択してください。アーティスト名、CD タイトル、および発売日がコンボ ボックスの下の詳細ビューに表示されます。
XAML
<!--The UI for the details view--> <StackPanel x:Name="RecordingDetails"> <TextBlock FontWeight="Bold" Text="{Binding Artist, Mode=OneWay}" Margin="5,0,0,0"/> <TextBlock FontStyle="Italic" Text="{Binding Name, Mode=OneWay}" Margin="5,0,0,0"/> <TextBlock Text="{Binding ReleaseDate, Mode=OneWay}" Margin="5,0,0,0" /> </StackPanel>
C#
ComboWithTemplate.SelectionChanged += new SelectionChangedEventHandler(ComboWithTemplate_SelectionChanged); ComboWithTemplate.SelectedIndex = 0;
...
void ComboWithTemplate_SelectionChanged(object sender, SelectionChangedEventArgs e) { ComboBox myCDs = sender as ComboBox; RecordingDetails.DataContext = MyMusic[myCDs.SelectedIndex]; }
Visual Basic
AddHandler ComboWithTemplate.SelectionChanged, _ AddressOf ComboWithTemplate_SelectionChanged ComboWithTemplate.SelectedIndex = 0
...
Private Sub ComboWithTemplate_SelectionChanged(ByVal sender As Object, _ ByVal e As SelectionChangedEventArgs) Dim myCDs As ComboBox = TryCast(sender, ComboBox) RecordingDetails.DataContext = MyMusic(myCDs.SelectedIndex) End Sub
この例では、既存のコンボ ボックスが格納されているユーザー コントロールに 1 つの StackPanel を追加し、Rectangle を ComboBox の下の分割線として使用しています。その下のスタック パネルには、音楽 CD の詳細を表示する 4 つのテキスト ブロックが含まれます。各テキスト ブロックの TextBlock.Text プロパティは、Recording オブジェクトのプロパティにバインドされています。詳細ビューの更新には、リスト ボックスの ListBox.SelectionChanged イベントを使用しており、イベント ハンドラーで FrameworkElement.DataContext に選択項目を設定しています。常にいずれかの項目が選択されているようにするため、ページの初期化時にリスト ボックス内の最初の項目を選択項目に設定しています。このサンプルを実行すると、コンボ ボックスのテキスト ボックス部分に選択項目が表示されます。
コントールに表示するためのデータ変換
TextBox などのコントロールで文字列以外のデータ型を書式設定および表示する場合は、コンバーターを使用できます。たとえば、既定の日時形式ではなくカスタム形式で日付を表示できます。
次の例では、音楽 CD リストの発売日の表示用にコンバーターを実装しています。このサンプルを実行するには、下向き矢印をクリックして、各 CD を選択してください。ドロップダウン リストと詳細ビューに発売日がカスタム形式で表示されます。
XAML
<UserControl x:Class="DataBindingControlsQuickStart4.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DataBindingControlsQuickStart4" Width="300" Height="200"> <UserControl.Resources> <local:StringFormatter x:Key="StringConverter"/> <UserControl.Resources /> <!--The UI for the details view--> <StackPanel x:Name="RecordingDetails"> <TextBlock Text="{Binding Artist, Mode=OneWay}" /> <TextBlock Text="{Binding Name, Mode=OneWay}" /> <TextBlock Text="{Binding ReleaseDate, Mode=OneWay, Converter={StaticResource StringConverter}, ConverterParameter=Released: \{0:d\}}" /> </StackPanel>
C#
public class StringFormatter : IValueConverter { // This converts the value object to the string to display. // This will work with most simple types. public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { // Retrieve the format string and use it to format the value. string formatString = parameter as string; if (!string.IsNullOrEmpty(formatString)) { return string.Format(culture, formatString, value); }
// If the format string is null or empty, simply // call ToString() on the value. return value.ToString(); }
// No need to implement converting back on a one-way binding public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
Visual Basic
Public Class StringFormatter Implements IValueConverter
' This converts the DateTime object to the string to display. Public Function Convert(ByVal value As Object, ByVal targetType As Type, _ ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _ As Object Implements IValueConverter.Convert
' Retrieve the format string and use it to format the value. Dim formatString As String = TryCast(parameter, String) If Not String.IsNullOrEmpty(formatString) Then Return String.Format(culture, formatString, value) End If
' If the format string is null or empty, simply call ToString() ' on the value. Return value.ToString() End Function
' No need to implement converting back on a one-way binding Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, _ ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) _ As Object Implements IValueConverter.ConvertBack Throw New NotImplementedException() End Function End Class
コンバーターは IValueConverter インターフェイスの派生クラスです。IValueConverter には、Convert と ConvertBack という 2 つのメソッドがあります。データ ソースからバインド ターゲットへの OneWay バインドでは、Convert メソッドを実装する必要があります。この例に示すコンバーターは非常によく使用されます。目的の文字列書式をパラメーターとして渡した場合、コンバーターは Format メソッドを使用して変換を行います。書式文字列が渡されなかった場合、コンバーターはオブジェクトに対して ToString を呼び出し、その結果を返します。
コンバーターを実装すると、コンバーター クラスのインスタンスを作成してバインドに使用することができます。この例では、XAML でこの処理を実行しています。コンバーターのインスタンスは静的リソースとして作成され、キーが割り当てられます。このキーは、コンバーター プロパティがバインド用に設定された場合に使用されます。データを変換してコントロールに表示する方法については、MSDN の Silverlight ドキュメントの「IValueConverter インターフェイス」を参照してください。
参照
フィードバックを送信する