Создание Xamarin.Forms DataTemplate
Шаблоны данных могут создаваться как встроенные в ResourceDictionary или из пользовательского типа или соответствующего типа ячейки Xamarin.Forms. В этой статье рассматривается каждый из способов.
Стандартный сценарий использования DataTemplate
— отображение данных из коллекции объектов в ListView
. Внешним видом данных в каждой ячейке ListView
можно управлять, присваивая свойству ListView.ItemTemplate
объект DataTemplate
. Это можно делать несколькими способами:
- Создание встроенного шаблона DataTemplate
- Создание шаблона DataTemplate с типом
- Создание шаблона DataTemplate как ресурса
Какой бы способ ни использовался, в результате внешний вид каждой ячейки ListView
определяется шаблоном DataTemplate
, как показано на следующих снимках экрана.
Создание встроенного шаблона DataTemplate
Свойству ListView.ItemTemplate
может быть присвоен встроенный шаблон DataTemplate
. Встроенный шаблон, который является прямым потомком соответствующего свойства элемента управления, следует использовать, если нет необходимости повторно использовать шаблон данных в другом месте. Элементы шаблона DataTemplate
определяют внешний вид каждой ячейки, как показано в следующем примере кода XAML.
<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
или производный от него тип. В этом примере используется класс ViewCell
, производный от Cell
. Управление макетом внутри ViewCell
осуществляется здесь с помощью Grid
. Макет Grid
содержит три экземпляра 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
.
Создание шаблона 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>
В этом случае свойству ListView.ItemTemplate
присвоен шаблон DataTemplate
, созданный на основе пользовательского типа, который определяет внешний вид ячейки. Пользовательский тип должен быть производным от типа 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
содержит три экземпляра 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;
}
}
Примечание.
Обратите внимание на то, что в Xamarin.Forms также есть типы ячеек, которые позволяют отображать простые данные в ячейках ListView
. Дополнительные сведения см. в статье Настройка внешнего вида ячейки.
Создание шаблона DataTemplate как ресурса
Шаблоны данных также можно создавать как повторно используемые объекты в ResourceDictionary
. Для этого каждому объявлению присваивается уникальный атрибут x:Key
, который предоставляет описательный ключ в ResourceDictionary
, как показано в следующем примере кода XAML.
<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>
Шаблон DataTemplate
присваивается свойству ListView.ItemTemplate
с помощью расширения разметки StaticResource
. Обратите внимание на то, что шаблон 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
добавляется в ResourceDictionary
с помощью метода Add
, задающего строку Key
. По ней можно ссылаться на шаблон DataTemplate
, который нужно извлечь.
Итоги
В этой статье были представлены сведения о создании шаблонов данных как встроенных, на основе пользовательского типа или в ResourceDictionary
. Встроенный шаблон следует использовать, если нет необходимости повторно использовать шаблон данных в другом месте. Шаблон данных можно использовать повторно, определив его как пользовательский тип или как ресурс на уровне элемента управления, страницы или приложения.