Xamarin.Forms DataTemplate の作成
データ テンプレートは、ResourceDictionary 内でインラインで作成したり、またはカスタム型や適切な Xamarin.Forms のセルの種類から作成したりできます。 この記事では、各手法について説明します。
DataTemplate
の一般的な使用シナリオは、ListView
でオブジェクトのコレクションのデータを表示することです。 ListView
の各セルのデータの外観は、ListView.ItemTemplate
プロパティを DataTemplate
に設定することで管理できます。 これを実現するために利用できる手法がいくつかあります。
使用する手法に関係なく、次のスクリーンショットに示すように、結果として ListView
の各セルの外観は DataTemplate
で定義されます。
インライン DataTemplate を作成する
ListView.ItemTemplate
プロパティはインライン DataTemplate
に設定できます。 インライン テンプレートは、適切なコントロール プロパティの直接の子として配置されるものであり、データ テンプレートを別の場所で再利用する必要がない場合に使用するようにします。 次の XAML コード例のように、DataTemplate
に指定された要素で各セルの外観を定義します。
<ListView Margin="0,20,0,0">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:Person}">
<local:Person Name="Steve" Age="21" Location="USA" />
<local:Person Name="John" Age="37" Location="USA" />
<local:Person Name="Tom" Age="42" Location="UK" />
<local:Person Name="Lucas" Age="29" Location="Germany" />
<local:Person Name="Tariq" Age="39" Location="UK" />
<local:Person Name="Jane" Age="30" Location="USA" />
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
...
<Label Text="{Binding Name}" FontAttributes="Bold" />
<Label Grid.Column="1" Text="{Binding Age}" />
<Label Grid.Column="2" Text="{Binding Location}" HorizontalTextAlignment="End" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
インライン DataTemplate
の子は、種類が Cell
か、そこから派生している必要があります。 この例では、Cell
から派生した ViewCell
が使われます。 ViewCell
内のレイアウトは Grid
で管理されています。 Grid
には 3 つの Label
インスタンスが含まれており、その Text
プロパティをコレクション内の各 Person
オブジェクトの適切なプロパティにバインドしています。
これと同じ C# コードの例は次のとおりです。
public class WithDataTemplatePageCS : ContentPage
{
public WithDataTemplatePageCS()
{
...
var people = new List<Person>
{
new Person { Name = "Steve", Age = 21, Location = "USA" },
...
};
var personDataTemplate = new DataTemplate(() =>
{
var grid = new Grid();
...
var nameLabel = new Label { FontAttributes = FontAttributes.Bold };
var ageLabel = new Label();
var locationLabel = new Label { HorizontalTextAlignment = TextAlignment.End };
nameLabel.SetBinding(Label.TextProperty, "Name");
ageLabel.SetBinding(Label.TextProperty, "Age");
locationLabel.SetBinding(Label.TextProperty, "Location");
grid.Children.Add(nameLabel);
grid.Children.Add(ageLabel, 1, 0);
grid.Children.Add(locationLabel, 2, 0);
return new ViewCell { View = grid };
});
Content = new StackLayout
{
Margin = new Thickness(20),
Children = {
...
new ListView { ItemsSource = people, ItemTemplate = personDataTemplate, Margin = new Thickness(0, 20, 0, 0) }
}
};
}
}
C# の場合、インライン DataTemplate
は、Func
引数を指定するコンストラクター オーバーロードを使用して作成されます。
Type を使用して DataTemplate を作成する
ListView.ItemTemplate
プロパティは、セルの種類から作成された DataTemplate
に設定することもできます。 このアプローチの利点は、アプリケーション全体で、セルの種類に定義された外観を複数のデータ テンプレートから再利用できることです。 このアプローチの例を次の XAML コードに示します。
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataTemplates"
...>
<StackLayout Margin="20">
...
<ListView Margin="0,20,0,0">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:Person}">
<local:Person Name="Steve" Age="21" Location="USA" />
...
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<local:PersonCell />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
ここでは、セルの外観を定義するカスタムの種類から作成された DataTemplate
に ListView.ItemTemplate
プロパティが設定されています。 次のコード例に示すように、カスタムの種類は、種類 ViewCell
から派生している必要があります。
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataTemplates.PersonCell">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.2*" />
<ColumnDefinition Width="0.3*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}" FontAttributes="Bold" />
<Label Grid.Column="1" Text="{Binding Age}" />
<Label Grid.Column="2" Text="{Binding Location}" HorizontalTextAlignment="End" />
</Grid>
</ViewCell>
ViewCell
内では、レイアウトは Grid
によってここで管理されます。 Grid
には 3 つの Label
インスタンスが含まれており、その Text
プロパティをコレクション内の各 Person
オブジェクトの適切なプロパティにバインドしています。
C# での同等のコード例を次に示します。
public class WithDataTemplatePageFromTypeCS : ContentPage
{
public WithDataTemplatePageFromTypeCS()
{
...
var people = new List<Person>
{
new Person { Name = "Steve", Age = 21, Location = "USA" },
...
};
Content = new StackLayout
{
Margin = new Thickness(20),
Children = {
...
new ListView { ItemTemplate = new DataTemplate(typeof(PersonCellCS)), ItemsSource = people, Margin = new Thickness(0, 20, 0, 0) }
}
};
}
}
C# の場合、DataTemplate
は、引数としてセルの種類を指定するコンストラクター オーバーロードを使用して作成されます。 次のコード例に示すように、セルの種類は、種類 ViewCell
から派生している必要があります。
public class PersonCellCS : ViewCell
{
public PersonCellCS()
{
var grid = new Grid();
...
var nameLabel = new Label { FontAttributes = FontAttributes.Bold };
var ageLabel = new Label();
var locationLabel = new Label { HorizontalTextAlignment = TextAlignment.End };
nameLabel.SetBinding(Label.TextProperty, "Name");
ageLabel.SetBinding(Label.TextProperty, "Age");
locationLabel.SetBinding(Label.TextProperty, "Location");
grid.Children.Add(nameLabel);
grid.Children.Add(ageLabel, 1, 0);
grid.Children.Add(locationLabel, 2, 0);
View = grid;
}
}
リソースとして DataTemplate を作成する
データ テンプレートは、ResourceDictionary
で再利用可能なオブジェクトとして作成することもできます。 これを実現するには、次の XAML コード例に示すように、ResourceDictionary
内に説明的なキーを提供する一意の x:Key
属性を各宣言に指定します。
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
...>
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="personTemplate">
<ViewCell>
<Grid>
...
</Grid>
</ViewCell>
</DataTemplate>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Margin="20">
...
<ListView ItemTemplate="{StaticResource personTemplate}" Margin="0,20,0,0">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:Person}">
<local:Person Name="Steve" Age="21" Location="USA" />
...
</x:Array>
</ListView.ItemsSource>
</ListView>
</StackLayout>
</ContentPage>
StaticResource
マークアップ拡張を使用して、DataTemplate
が ListView.ItemTemplate
プロパティに割り当てられます。 DataTemplate
はページの ResourceDictionary
で定義されていますが、コントロール レベルまたはアプリケーション レベルで定義することもできる点に注意してください。
C# での同等のページのコード例を次に示します。
public class WithDataTemplatePageCS : ContentPage
{
public WithDataTemplatePageCS ()
{
...
var personDataTemplate = new DataTemplate (() => {
var grid = new Grid ();
...
return new ViewCell { View = grid };
});
Resources = new ResourceDictionary ();
Resources.Add ("personTemplate", personDataTemplate);
Content = new StackLayout {
Margin = new Thickness(20),
Children = {
...
new ListView { ItemTemplate = (DataTemplate)Resources ["personTemplate"], ItemsSource = people };
}
};
}
}
DataTemplate
は、Add
メソッドを使用して ResourceDictionary
に追加されます。これで、取得時に DataTemplate
を参照するために使用される Key
文字列が指定されます。
まとめ
この記事では、インライン、カスタムの種類、または ResourceDictionary
でデータ テンプレートを作成する方法について説明しました。 データ テンプレートを他の場所で再利用する必要がない場合は、インライン テンプレートを使用する必要があります。 または、データ テンプレートをカスタム型として定義することで、あるいは制御レベル、ページ レベル、またはアプリケーション レベルのリソースとして定義することで、それを再利用できます。