ListView データ ソース
Xamarin.FormsListView
は、データのリストを表示するために使用されます。 この記事では、ListView
にデータを設定する方法と、選択した項目にデータをバインドする方法について説明します。
ItemsSource
ListView
には、IEnumerable
を実装している任意のコレクションを受け入れることができる ItemsSource
プロパティを使用してデータを設定します。 ListView
を設定する最も簡単な方法は、以下のように文字列の配列を使用することです。
<ListView>
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>mono</x:String>
<x:String>monodroid</x:String>
<x:String>monotouch</x:String>
<x:String>monorail</x:String>
<x:String>monodevelop</x:String>
<x:String>monotone</x:String>
<x:String>monopoly</x:String>
<x:String>monomodal</x:String>
<x:String>mononucleosis</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
同等の C# コードを次に示します。
var listView = new ListView();
listView.ItemsSource = new string[]
{
"mono",
"monodroid",
"monotouch",
"monorail",
"monodevelop",
"monotone",
"monopoly",
"monomodal",
"mononucleosis"
};
この方法では、文字列のリストを使用して ListView
を設定します。 既定では、ListView
は ToString
を呼び出して各行の TextCell
に結果を表示します。 データの表示方法をカスタマイズするには、「セルの外観」を参照してください。
ItemsSource
は配列に送信されてしまっているため、基になるリストまたは配列が変更されても、その内容は更新されません。 基になるリストで項目の追加、削除、変更が行われたときに ListView を自動的に更新したい場合は、ObservableCollection
を使用する必要があります。 以下のように ObservableCollection
は System.Collections.ObjectModel
内で定義され、List
と似ていますが、これは ListView
に任意の変更を通知できるという違いがあります。
ObservableCollection<Employee> employees = new ObservableCollection<Employee>();
listView.ItemsSource = employees;
//Mr. Mono will be added to the ListView because it uses an ObservableCollection
employees.Add(new Employee(){ DisplayName="Mr. Mono"});
データ バインディング
データ バインディングは、ユーザー インターフェイス オブジェクトのプロパティを、ビューモデル内のクラスなどの何らかの CLR オブジェクトのプロパティにバインドする "接着剤" です。 データ バインディングは、多くの退屈な定型コードを置き換えることで、ユーザー インターフェイスの開発を簡略化できるため便利です。
データ バインディングは、バインドされた値の変化に合わせてオブジェクトの同期を保つことで機能します。 コントロールの値が変更されたときのためのイベント ハンドラーを記述する代わりに、バインディングを確立し、ビューモデル内でバインディングを有効にします。
データ バインディングの詳細については、Xamarin.Forms XAML の基本に関する記事シリーズのパート 4 である「データ バインディングの基本」を参照してください。
セルのバインディング
セル (およびセルの子) のプロパティは、ItemsSource
内のオブジェクトのプロパティにバインドできます。 たとえば、ListView
は従業員のリストを表現するために使用できます。
従業員クラス:
public class Employee
{
public string DisplayName {get; set;}
}
ObservableCollection<Employee>
が作成され、ListView
ItemsSource
として設定され、リストにデータが入力されます。
ObservableCollection<Employee> employees = new ObservableCollection<Employee>();
public ObservableCollection<Employee> Employees { get { return employees; }}
public EmployeeListPage()
{
EmployeeView.ItemsSource = employees;
// ObservableCollection allows items to be added after ItemsSource
// is set and the UI will react to changes
employees.Add(new Employee{ DisplayName="Rob Finnerty"});
employees.Add(new Employee{ DisplayName="Bill Wrestler"});
employees.Add(new Employee{ DisplayName="Dr. Geri-Beth Hooper"});
employees.Add(new Employee{ DisplayName="Dr. Keith Joyce-Purdy"});
employees.Add(new Employee{ DisplayName="Sheri Spruce"});
employees.Add(new Employee{ DisplayName="Burt Indybrick"});
}
警告
ListView
は基になる ObservableCollection
における変更に応じて更新されますが、別の ObservableCollection
インスタンスが元の ObservableCollection
参照 (例: employees = otherObservableCollection;
) に割り当てられている場合、ListView
は更新されません。
次のスニペットは、従業員のリストにバインドされた ListView
を示しています。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:constants="clr-namespace:XamarinFormsSample;assembly=XamarinFormsXamlSample"
x:Class="XamarinFormsXamlSample.Views.EmployeeListPage"
Title="Employee List">
<ListView x:Name="EmployeeView"
ItemsSource="{Binding Employees}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding DisplayName}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
この XAML の例では、ListView
を含む ContentPage
を定義しています。 ListView
のデータ ソースは、ItemsSource
属性を使用して設定されます。 ItemsSource
の各行のレイアウトは、ListView.ItemTemplate
要素内で定義されます。 この結果は、次のスクリーンショットのようになります。
警告
ObservableCollection
はスレッド セーフではありません。 ObservableCollection
を変更すると、その変更を実行したのと同じスレッドで UI の更新が行われます。 そのスレッドがプライマリ UI スレッドでない場合は、例外が発生します。
SelectedItem のバインディング
イベント ハンドラーを使用して変更に応答するのではなく、ListView
の選択した項目に対してバインドを行いたい場合がよくあります。 XAML でこれを行うには、以下のように SelectedItem
プロパティをバインドします。
<ListView x:Name="listView"
SelectedItem="{Binding Source={x:Reference SomeLabel},
Path=Text}">
…
</ListView>
listView
の ItemsSource
が文字列のリストであるという仮定の下で、SomeLabel
は Text
プロパティを SelectedItem
にバインドします。