Настройка ViewCell
ViewCell в Xamarin.Forms — это ячейка, которую можно добавить в представление ListView или TableView и которая содержит представления, определяемые разработчиком. В этой статье показано, как создать пользовательский отрисовщик для ячейки ViewCell, размещенной в элементе управления ListView Xamarin.Forms. Это останавливает Xamarin.Forms многократное вызов вычислений макета во время прокрутки ListView.
Каждая ячейка Xamarin.Forms имеет сопутствующий отрисовщик для каждой платформы, который создает экземпляр собственного элемента управления. Когда ViewCell
отображается в приложении Xamarin.Forms, на платформе iOS создается класс ViewCellRenderer
, который, в свою очередь, создает собственный элемент управления UITableViewCell
. На платформе Android класс ViewCellRenderer
создает собственный элемент управления View
. На универсальной платформе Windows (UWP) класс ViewCellRenderer
создает собственный элемент управления DataTemplate
. Дополнительные сведения об отрисовщике и классах собственных элементов управления, с которыми сопоставляются элементы управления Xamarin.Forms, см. в статье Базовые классы и собственные элементы управления отрисовщика.
На следующей схеме показана связь между классом ViewCell
и соответствующими собственными элементами управления, которые его реализуют:
Процесс отрисовки можно использовать для реализации настроек конкретных платформ путем создания пользовательского отрисовщика для ViewCell
на каждой платформе. Этот процесс выглядит следующим образом:
- Создание пользовательской ячейки Xamarin.Forms.
- Использование пользовательской ячейки в Xamarin.Forms.
- Создание пользовательского отрисовщика для ячейки для каждой платформы.
Теперь каждый элемент будет обсуждаться в свою очередь для реализации NativeCell
отрисовщика, который использует преимущества макета для конкретной платформы для каждой ячейки, размещенной Xamarin.FormsListView
внутри элемента управления. Это предотвратит постоянные вызовы вычисления макета Xamarin.Forms во время прокрутки ListView
.
Создание пользовательской ячейки
Пользовательский элемент управления ячейки можно создать путем создания подклассов класса ViewCell
, как показано в следующем примере кода.
public class NativeCell : ViewCell
{
public static readonly BindableProperty NameProperty =
BindableProperty.Create ("Name", typeof(string), typeof(NativeCell), "");
public string Name {
get { return (string)GetValue (NameProperty); }
set { SetValue (NameProperty, value); }
}
public static readonly BindableProperty CategoryProperty =
BindableProperty.Create ("Category", typeof(string), typeof(NativeCell), "");
public string Category {
get { return (string)GetValue (CategoryProperty); }
set { SetValue (CategoryProperty, value); }
}
public static readonly BindableProperty ImageFilenameProperty =
BindableProperty.Create ("ImageFilename", typeof(string), typeof(NativeCell), "");
public string ImageFilename {
get { return (string)GetValue (ImageFilenameProperty); }
set { SetValue (ImageFilenameProperty, value); }
}
}
Класс NativeCell
создается в проекте библиотеки .NET Standard и определяет API для пользовательской ячейки. Пользовательская ячейка предоставляет свойства Name
, Category
и ImageFilename
, которые могут отображаться посредством привязки данных. Дополнительные сведения о привязке данных см. в статье Основы привязки данных.
Использование пользовательской ячейки
На пользовательскую ячейку NativeCell
можно ссылаться в XAML в проекте библиотеки .NET Standard, объявив пространство имен для ее расположения и используя префикс пространства имен в элементе пользовательской ячейки. В следующем примере кода показано, как пользовательская ячейка NativeCell
может использоваться страницей XAML.
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
...>
...
<ContentPage.Content>
<StackLayout>
<Label Text="Xamarin.Forms native cell" HorizontalTextAlignment="Center" />
<ListView x:Name="listView" CachingStrategy="RecycleElement" ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<local:NativeCell Name="{Binding Name}" Category="{Binding Category}" ImageFilename="{Binding ImageFilename}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Префикс пространства имен local
может иметь любое имя. Тем не менее значения clr-namespace
и assembly
должны соответствовать данным пользовательского элемента управления. После объявления пространства имен префикс используется для ссылки на пользовательскую ячейку.
В следующем примере кода показано, как пользовательская ячейка NativeCell
может использоваться страницей C#.
public class NativeCellPageCS : ContentPage
{
ListView listView;
public NativeCellPageCS()
{
listView = new ListView(ListViewCachingStrategy.RecycleElement)
{
ItemsSource = DataSource.GetList(),
ItemTemplate = new DataTemplate(() =>
{
var nativeCell = new NativeCell();
nativeCell.SetBinding(NativeCell.NameProperty, "Name");
nativeCell.SetBinding(NativeCell.CategoryProperty, "Category");
nativeCell.SetBinding(NativeCell.ImageFilenameProperty, "ImageFilename");
return nativeCell;
})
};
switch (Device.RuntimePlatform)
{
case Device.iOS:
Padding = new Thickness(0, 20, 0, 0);
break;
case Device.Android:
case Device.UWP:
Padding = new Thickness(0);
break;
}
Content = new StackLayout
{
Children = {
new Label { Text = "Xamarin.Forms native cell", HorizontalTextAlignment = TextAlignment.Center },
listView
}
};
listView.ItemSelected += OnItemSelected;
}
...
}
Элемент Xamarin.FormsListView
управления используется для отображения списка данных, заполненного свойством ItemSource
. Стратегия кэширования RecycleElement
пытается свести к минимуму объем занимаемой памяти ListView
и время выполнения путем повторного использования ячеек списка. Дополнительные сведения см. в разделе Стратегия кэширования.
Каждая строка в списке содержит три элемента данных — имя, категорию и имя файла изображения. Макет каждой строки в списке определяется DataTemplate
со ссылкой через привязываемое свойство ListView.ItemTemplate
. DataTemplate
определяет, что каждая строка данных в списке будет ячейкой NativeCell
, отображающей свойства Name
, Category
и ImageFilename
посредством привязки данных. Дополнительные сведения об элементе управления ListView
см. в статье ListView.
Теперь в каждый проект приложения можно добавить пользовательский отрисовщик для настройки определяемого платформой макета для каждой ячейки.
Создание пользовательского отрисовщика на каждой платформе
Процесс создания класса пользовательского отрисовщика выглядит следующим образом:
- Создайте подкласс класса
ViewCellRenderer
, который отрисовывает пользовательскую ячейку. - Переопределите зависящий от платформы метод, который отрисовывает пользовательскую ячейку, и напишите логику для его настройки.
- Добавьте атрибут
ExportRenderer
в класс настраиваемого отрисовщика, чтобы указать, что он будет использоваться для отрисовки пользовательской ячейки Xamarin.Forms. Этот атрибут используется для регистрации пользовательского отрисовщика в Xamarin.Forms.
Примечание.
Для большинства элементов Xamarin.Forms предоставлять пользовательский отрисовщик в проекте для каждой платформы необязательно. Если пользовательский отрисовщик не зарегистрирован, будет использоваться отрисовщик по умолчанию для базового класса элемента управления. Однако пользовательские отрисовщики необходимы в каждом зависящем от платформы проекте при отрисовке элемента ViewCell.
На следующей схеме показаны обязанности каждого проекта в примере приложения, а также связи между ними:
Пользовательская ячейка NativeCell
отрисовывается с помощью зависящих от платформы классов отрисовщика, которые являются производными от класса ViewCellRenderer
каждой платформы. Это приводит к тому, что каждая пользовательская ячейка NativeCell
отрисовывается с помощью зависящих от платформы макетов, как показано на следующих снимках экрана.
Класс ViewCellRenderer
предоставляет зависящие от платформы методы для отрисовки пользовательской ячейки. Метод GetCell
предназначен для платформы iOS, метод GetCellCore
— для платформы Android, а метод GetTemplate
— для универсальной платформы Windows.
Каждый класс пользовательского отрисовщика дополняется атрибутом ExportRenderer
, который регистрирует отрисовщик в Xamarin.Forms. Атрибут принимает два параметра — имя типа отрисовываемой ячейки Xamarin.Forms и имя типа пользовательского отрисовщика. Префикс assembly
в атрибуте указывает, что атрибут применяется ко всей сборке.
В следующих разделах рассматривается реализация класса пользовательского отрисовщика для каждой платформы.
Создание пользовательского отрисовщика в iOS
В следующем примере кода показан пользовательский отрисовщик для платформы iOS:
[assembly: ExportRenderer(typeof(NativeCell), typeof(NativeiOSCellRenderer))]
namespace CustomRenderer.iOS
{
public class NativeiOSCellRenderer : ViewCellRenderer
{
NativeiOSCell cell;
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
var nativeCell = (NativeCell)item;
cell = reusableCell as NativeiOSCell;
if (cell == null)
cell = new NativeiOSCell(item.GetType().FullName, nativeCell);
else
cell.NativeCell.PropertyChanged -= OnNativeCellPropertyChanged;
nativeCell.PropertyChanged += OnNativeCellPropertyChanged;
cell.UpdateCell(nativeCell);
return cell;
}
...
}
}
Метод GetCell
вызывается для создания каждой отображаемой ячейки. Каждая ячейка является экземпляром элемента NativeiOSCell
, который определяет макет ячейки и ее данные. Работа метода GetCell
зависит от стратегии кэширования ListView
.
Если стратегией кэширования
ListView
являетсяRetainElement
, методGetCell
будет вызываться для каждой ячейки. ЭкземплярNativeiOSCell
будет создан для каждого экземпляраNativeCell
, который отображается на экране. Когда пользователь прокручиваетListView
, экземплярыNativeiOSCell
будут использоваться повторно. Дополнительные сведения о повторном использовании ячеек в iOS см. в разделе Повторное использование ячеек.Примечание.
Этот код пользовательского отрисовщика выполнит повторное использование некоторых ячеек, даже если для
ListView
задано сохранение ячеек.Данные, отображаемые каждым экземпляром
NativeiOSCell
, созданным или повторно используемым, будут заменены данными из каждого экземпляраNativeCell
методомUpdateCell
.Примечание.
Метод
OnNativeCellPropertyChanged
никогда не будет вызываться, если в качестве стратегии кэшированияListView
задано сохранение ячеек.Если стратегией кэширования
ListView
являетсяRecycleElement
, методGetCell
будет вызываться для каждой ячейки, которая изначально отображалась на экране. ЭкземплярNativeiOSCell
будет создан для каждого экземпляраNativeCell
, который отображается на экране. Данные, отображаемые каждым экземпляромNativeiOSCell
, будут заменены данными из экземпляраNativeCell
методомUpdateCell
. Тем не менее методGetCell
не будет вызываться, когда пользователь прокручиваетListView
. Вместо этого экземплярыNativeiOSCell
будут использоваться повторно. СобытияPropertyChanged
будут вызваны для экземпляраNativeCell
при изменении его данных, и обработчик событийOnNativeCellPropertyChanged
обновит данные в каждом повторно используемом экземпляреNativeiOSCell
.
В следующем примере кода показан метод OnNativeCellPropertyChanged
, который вызывается при вызове события PropertyChanged
.
namespace CustomRenderer.iOS
{
public class NativeiOSCellRenderer : ViewCellRenderer
{
...
void OnNativeCellPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var nativeCell = (NativeCell)sender;
if (e.PropertyName == NativeCell.NameProperty.PropertyName)
{
cell.HeadingLabel.Text = nativeCell.Name;
}
else if (e.PropertyName == NativeCell.CategoryProperty.PropertyName)
{
cell.SubheadingLabel.Text = nativeCell.Category;
}
else if (e.PropertyName == NativeCell.ImageFilenameProperty.PropertyName)
{
cell.CellImageView.Image = cell.GetImage(nativeCell.ImageFilename);
}
}
}
}
Этот метод обновляет данные, отображаемые повторно используемыми экземплярами NativeiOSCell
. Выполняется проверка изменяемого свойства, так как метод может вызываться несколько раз.
Класс NativeiOSCell
определяет макет для каждой ячейки и показан в следующем примере кода.
internal class NativeiOSCell : UITableViewCell, INativeElementView
{
public UILabel HeadingLabel { get; set; }
public UILabel SubheadingLabel { get; set; }
public UIImageView CellImageView { get; set; }
public NativeCell NativeCell { get; private set; }
public Element Element => NativeCell;
public NativeiOSCell(string cellId, NativeCell cell) : base(UITableViewCellStyle.Default, cellId)
{
NativeCell = cell;
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.FromRGB(255, 255, 224);
CellImageView = new UIImageView();
HeadingLabel = new UILabel()
{
Font = UIFont.FromName("Cochin-BoldItalic", 22f),
TextColor = UIColor.FromRGB(127, 51, 0),
BackgroundColor = UIColor.Clear
};
SubheadingLabel = new UILabel()
{
Font = UIFont.FromName("AmericanTypewriter", 12f),
TextColor = UIColor.FromRGB(38, 127, 0),
TextAlignment = UITextAlignment.Center,
BackgroundColor = UIColor.Clear
};
ContentView.Add(HeadingLabel);
ContentView.Add(SubheadingLabel);
ContentView.Add(CellImageView);
}
public void UpdateCell(NativeCell cell)
{
HeadingLabel.Text = cell.Name;
SubheadingLabel.Text = cell.Category;
CellImageView.Image = GetImage(cell.ImageFilename);
}
public UIImage GetImage(string filename)
{
return (!string.IsNullOrWhiteSpace(filename)) ? UIImage.FromFile("Images/" + filename + ".jpg") : null;
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
HeadingLabel.Frame = new CGRect(5, 4, ContentView.Bounds.Width - 63, 25);
SubheadingLabel.Frame = new CGRect(100, 18, 100, 20);
CellImageView.Frame = new CGRect(ContentView.Bounds.Width - 63, 5, 33, 33);
}
}
Этот класс определяет элементы управления, используемые для отрисовки содержимого ячейки и макета. Этот класс реализует интерфейс INativeElementView
, который является обязательным, если ListView
использует стратегию кэширования RecycleElement
. Этот интерфейс указывает, что класс должен реализовывать свойство Element
, которое должно возвращать данные пользовательской ячейки для повторно используемых ячеек.
Конструктор NativeiOSCell
инициализирует внешний вид свойств HeadingLabel
, SubheadingLabel
и CellImageView
. Эти свойства используются для отображения данных, хранящихся в экземпляре NativeCell
, с помощью метода UpdateCell
, вызываемого для задания значения каждого свойства. Кроме того, когда ListView
использует стратегию кэширования RecycleElement
, данные, отображаемые свойствами HeadingLabel
, SubheadingLabel
и CellImageView
, могут быть обновлены методом OnNativeCellPropertyChanged
в пользовательском отрисовщике.
Макет ячейки осуществляется переопределением LayoutSubviews
, которое задает координаты HeadingLabel
, SubheadingLabel
и CellImageView
в ячейке.
Создание пользовательского отрисовщика в Android
В следующем примере кода показан пользовательский отрисовщик для платформы Android:
[assembly: ExportRenderer(typeof(NativeCell), typeof(NativeAndroidCellRenderer))]
namespace CustomRenderer.Droid
{
public class NativeAndroidCellRenderer : ViewCellRenderer
{
NativeAndroidCell cell;
protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, ViewGroup parent, Context context)
{
var nativeCell = (NativeCell)item;
Console.WriteLine("\t\t" + nativeCell.Name);
cell = convertView as NativeAndroidCell;
if (cell == null)
{
cell = new NativeAndroidCell(context, nativeCell);
}
else
{
cell.NativeCell.PropertyChanged -= OnNativeCellPropertyChanged;
}
nativeCell.PropertyChanged += OnNativeCellPropertyChanged;
cell.UpdateCell(nativeCell);
return cell;
}
...
}
}
Метод GetCellCore
вызывается для создания каждой отображаемой ячейки. Каждая ячейка является экземпляром элемента NativeAndroidCell
, который определяет макет ячейки и ее данные. Работа метода GetCellCore
зависит от стратегии кэширования ListView
.
Если стратегией кэширования
ListView
являетсяRetainElement
, методGetCellCore
будет вызываться для каждой ячейки.NativeAndroidCell
будет создан для каждого экземпляраNativeCell
, который отображается на экране. Когда пользователь прокручиваетListView
, экземплярыNativeAndroidCell
будут использоваться повторно. Дополнительные сведения о повторном использовании ячеек в Android см. в разделе Повторное использование представления строк.Примечание.
Учтите, что этот код пользовательского отрисовщика выполнит повторное использование некоторых ячеек, даже если для
ListView
задано сохранение ячеек.Данные, отображаемые каждым экземпляром
NativeAndroidCell
, созданным или повторно используемым, будут заменены данными из каждого экземпляраNativeCell
методомUpdateCell
.Примечание.
Обратите внимание, что, хотя метод
OnNativeCellPropertyChanged
будет вызываться, если в качестве стратегииListView
задано сохранение ячеек, он не будет обновлять значения свойстваNativeAndroidCell
.Если стратегией кэширования
ListView
являетсяRecycleElement
, методGetCellCore
будет вызываться для каждой ячейки, которая изначально отображалась на экране. ЭкземплярNativeAndroidCell
будет создан для каждого экземпляраNativeCell
, который отображается на экране. Данные, отображаемые каждым экземпляромNativeAndroidCell
, будут заменены данными из экземпляраNativeCell
методомUpdateCell
. Тем не менее методGetCellCore
не будет вызываться, когда пользователь прокручиваетListView
. Вместо этого экземплярыNativeAndroidCell
будут использоваться повторно. СобытияPropertyChanged
будут вызваны для экземпляраNativeCell
при изменении его данных, и обработчик событийOnNativeCellPropertyChanged
обновит данные в каждом повторно используемом экземпляреNativeAndroidCell
.
В следующем примере кода показан метод OnNativeCellPropertyChanged
, который вызывается при вызове события PropertyChanged
.
namespace CustomRenderer.Droid
{
public class NativeAndroidCellRenderer : ViewCellRenderer
{
...
void OnNativeCellPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var nativeCell = (NativeCell)sender;
if (e.PropertyName == NativeCell.NameProperty.PropertyName)
{
cell.HeadingTextView.Text = nativeCell.Name;
}
else if (e.PropertyName == NativeCell.CategoryProperty.PropertyName)
{
cell.SubheadingTextView.Text = nativeCell.Category;
}
else if (e.PropertyName == NativeCell.ImageFilenameProperty.PropertyName)
{
cell.SetImage(nativeCell.ImageFilename);
}
}
}
}
Этот метод обновляет данные, отображаемые повторно используемыми экземплярами NativeAndroidCell
. Выполняется проверка изменяемого свойства, так как метод может вызываться несколько раз.
Класс NativeAndroidCell
определяет макет для каждой ячейки и показан в следующем примере кода.
internal class NativeAndroidCell : LinearLayout, INativeElementView
{
public TextView HeadingTextView { get; set; }
public TextView SubheadingTextView { get; set; }
public ImageView ImageView { get; set; }
public NativeCell NativeCell { get; private set; }
public Element Element => NativeCell;
public NativeAndroidCell(Context context, NativeCell cell) : base(context)
{
NativeCell = cell;
var view = (context as Activity).LayoutInflater.Inflate(Resource.Layout.NativeAndroidCell, null);
HeadingTextView = view.FindViewById<TextView>(Resource.Id.HeadingText);
SubheadingTextView = view.FindViewById<TextView>(Resource.Id.SubheadingText);
ImageView = view.FindViewById<ImageView>(Resource.Id.Image);
AddView(view);
}
public void UpdateCell(NativeCell cell)
{
HeadingTextView.Text = cell.Name;
SubheadingTextView.Text = cell.Category;
// Dispose of the old image
if (ImageView.Drawable != null)
{
using (var image = ImageView.Drawable as BitmapDrawable)
{
if (image != null)
{
if (image.Bitmap != null)
{
image.Bitmap.Dispose();
}
}
}
}
SetImage(cell.ImageFilename);
}
public void SetImage(string filename)
{
if (!string.IsNullOrWhiteSpace(filename))
{
// Display new image
Context.Resources.GetBitmapAsync(filename).ContinueWith((t) =>
{
var bitmap = t.Result;
if (bitmap != null)
{
ImageView.SetImageBitmap(bitmap);
bitmap.Dispose();
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
else
{
// Clear the image
ImageView.SetImageBitmap(null);
}
}
}
Этот класс определяет элементы управления, используемые для отрисовки содержимого ячейки и макета. Этот класс реализует интерфейс INativeElementView
, который является обязательным, если ListView
использует стратегию кэширования RecycleElement
. Этот интерфейс указывает, что класс должен реализовывать свойство Element
, которое должно возвращать данные пользовательской ячейки для повторно используемых ячеек.
Конструктор NativeAndroidCell
расширяет макет NativeAndroidCell
и инициализирует свойства HeadingTextView
, SubheadingTextView
и ImageView
в элементы управления в расширенном макете. Эти свойства используются для отображения данных, хранящихся в экземпляре NativeCell
, с помощью метода UpdateCell
, вызываемого для задания значения каждого свойства. Кроме того, когда ListView
использует стратегию кэширования RecycleElement
, данные, отображаемые свойствами HeadingTextView
, SubheadingTextView
и ImageView
, могут быть обновлены методом OnNativeCellPropertyChanged
в пользовательском отрисовщике.
В следующем примере кода показано определение макета для файла макета NativeAndroidCell.axml
.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:background="@drawable/CustomSelector">
<LinearLayout
android:id="@+id/Text"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dip">
<TextView
android:id="@+id/HeadingText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF7F3300"
android:textSize="20dip"
android:textStyle="italic" />
<TextView
android:id="@+id/SubheadingText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dip"
android:textColor="#FF267F00"
android:paddingLeft="100dip" />
</LinearLayout>
<ImageView
android:id="@+id/Image"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="5dp"
android:src="@drawable/icon"
android:layout_alignParentRight="true" />
</RelativeLayout>
Этот макет указывает, что два элемента управления TextView
и элемент управления ImageView
используются для отображения содержимого ячейки. Два элемента управления TextView
расположены вертикально в элементе управления LinearLayout
, и все элементы управления содержатся в RelativeLayout
.
Создание пользовательского отрисовщика на универсальной платформе Windows
В следующем примере кода показан пользовательский отрисовщик для платформы UWP:
[assembly: ExportRenderer(typeof(NativeCell), typeof(NativeUWPCellRenderer))]
namespace CustomRenderer.UWP
{
public class NativeUWPCellRenderer : ViewCellRenderer
{
public override Windows.UI.Xaml.DataTemplate GetTemplate(Cell cell)
{
return App.Current.Resources["ListViewItemTemplate"] as Windows.UI.Xaml.DataTemplate;
}
}
}
Метод GetTemplate
вызывается для возвращения ячейки для отрисовки для каждой строки данных в списке. Он создает DataTemplate
для каждого экземпляра NativeCell
, который будет отображаться на экране с элементом DataTemplate
, определяющим внешний вид и содержимое ячейки.
DataTemplate
хранится в словаре ресурсов на уровне приложения и приводится в следующем примере кода.
<DataTemplate x:Key="ListViewItemTemplate">
<Grid Background="LightYellow">
<Grid.Resources>
<local:ConcatImageExtensionConverter x:Name="ConcatImageExtensionConverter" />
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.40*" />
<ColumnDefinition Width="0.40*"/>
<ColumnDefinition Width="0.20*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.ColumnSpan="2" Foreground="#7F3300" FontStyle="Italic" FontSize="22" VerticalAlignment="Top" Text="{Binding Name}" />
<TextBlock Grid.RowSpan="2" Grid.Column="1" Foreground="#267F00" FontWeight="Bold" FontSize="12" VerticalAlignment="Bottom" Text="{Binding Category}" />
<Image Grid.RowSpan="2" Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Center" Source="{Binding ImageFilename, Converter={StaticResource ConcatImageExtensionConverter}}" Width="50" Height="50" />
<Line Grid.Row="1" Grid.ColumnSpan="3" X1="0" X2="1" Margin="30,20,0,0" StrokeThickness="1" Stroke="LightGray" Stretch="Fill" VerticalAlignment="Bottom" />
</Grid>
</DataTemplate>
DataTemplate
определяет элементы управления, используемые для отображения содержимого ячейки, его макета и внешнего вида. Два элемента управления TextBlock
и элемент управления Image
используются для отображения содержимого ячейки с помощью привязки данных. Кроме того, экземпляр ConcatImageExtensionConverter
используется для сцепления расширения файла .jpg
с каждым именем файла изображения. Это гарантирует, что элемент управления Image
может загрузить и отрисовать изображение, когда его свойство Source
задано.
Итоги
В этой статье показано, как создать пользовательский отрисовщик для ViewCell
размещенного Xamarin.FormsListView
внутри элемента управления. Это предотвратит постоянные вызовы вычисления макета Xamarin.Forms во время прокрутки ListView
.