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 を設定します。 既定では、ListViewToString を呼び出して各行の TextCell に結果を表示します。 データの表示方法をカスタマイズするには、「セルの外観」を参照してください。

ItemsSource は配列に送信されてしまっているため、基になるリストまたは配列が変更されても、その内容は更新されません。 基になるリストで項目の追加、削除、変更が行われたときに ListView を自動的に更新したい場合は、ObservableCollection を使用する必要があります。 以下のように ObservableCollectionSystem.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 要素内で定義されます。 この結果は、次のスクリーンショットのようになります。

データ バインディングを使用した ListView

警告

ObservableCollection はスレッド セーフではありません。 ObservableCollection を変更すると、その変更を実行したのと同じスレッドで UI の更新が行われます。 そのスレッドがプライマリ UI スレッドでない場合は、例外が発生します。

SelectedItem のバインディング

イベント ハンドラーを使用して変更に応答するのではなく、ListView の選択した項目に対してバインドを行いたい場合がよくあります。 XAML でこれを行うには、以下のように SelectedItem プロパティをバインドします。

<ListView x:Name="listView"
          SelectedItem="{Binding Source={x:Reference SomeLabel},
          Path=Text}">
 …
</ListView>

listViewItemsSource が文字列のリストであるという仮定の下で、SomeLabelText プロパティを SelectedItem にバインドします。