Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Obiekt Xamarin.Forms ViewCell to komórka, którą można dodać do widoku ListView lub TableView, który zawiera widok zdefiniowany przez dewelopera. W tym artykule pokazano, jak utworzyć niestandardowy moduł renderujący dla kontrolki ViewCell hostowanej w kontrolce Xamarin.Forms ListView. Xamarin.Forms Uniemożliwia to wielokrotne wywoływanie obliczeń układu podczas przewijania elementu ListView.
Każda Xamarin.Forms komórka ma towarzyszący moduł renderujący dla każdej platformy, który tworzy wystąpienie kontrolki natywnej. Gdy element ViewCell jest renderowany przez aplikację Xamarin.Forms , w systemie iOS ViewCellRenderer klasę tworzy wystąpienie, co z kolei tworzy wystąpienie kontrolki natywnej UITableViewCell . Na platformie ViewCellRenderer Android klasa tworzy wystąpienie natywnej View kontrolki. W platforma uniwersalna systemu Windows (UWP) ViewCellRenderer klasa tworzy wystąpienie natywnej DataTemplateklasy . Aby uzyskać więcej informacji na temat klasy renderera i natywnych kontrolek mapowanych Xamarin.Forms na, zobacz Renderer Base Classes and Native Controls (Klasy bazowe modułu renderowania i kontrolki natywne).
Na poniższym diagramie przedstawiono relację między kontrolkami ViewCell macierzystymi i odpowiadającymi im kontrolkami natywnymi, które je implementują:

Proces renderowania można wykorzystać w celu zaimplementowania dostosowań specyficznych dla platformy przez utworzenie niestandardowego modułu renderowania dla elementu na ViewCell każdej platformie. Proces wykonywania tej czynności jest następujący:
- Utwórz komórkę niestandardową Xamarin.Forms .
- Zużyj komórkę niestandardową z Xamarin.Formspliku .
- Utwórz niestandardowy moduł renderowania dla komórki na każdej platformie.
Każdy element zostanie omówiony z kolei w celu zaimplementowania NativeCell modułu renderowania, który korzysta z układu specyficznego dla platformy dla każdej komórki hostowanej wewnątrz kontrolki Xamarin.FormsListView . Xamarin.Forms Uniemożliwia to wielokrotne wywoływanie obliczeń układu podczas ListView przewijania.
Tworzenie komórki niestandardowej
Niestandardową kontrolkę komórki można utworzyć przez podklasę ViewCell klasy, jak pokazano w poniższym przykładzie kodu:
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); }
}
}
Klasa jest tworzona NativeCell w projekcie biblioteki .NET Standard i definiuje interfejs API dla komórki niestandardowej. Komórka niestandardowa uwidacznia Namewłaściwości , Categoryi ImageFilename , które mogą być wyświetlane za pomocą powiązania danych. Aby uzyskać więcej informacji na temat powiązania danych, zobacz Podstawy powiązań danych.
Korzystanie z komórki niestandardowej
Do NativeCell komórki niestandardowej można odwoływać się w pliku Xaml w projekcie biblioteki .NET Standard, deklarując przestrzeń nazw dla swojej lokalizacji i używając prefiksu przestrzeni nazw w niestandardowym elemencie komórki. Poniższy przykład kodu przedstawia sposób NativeCell korzystania z komórki niestandardowej przez stronę 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>
Prefiks local przestrzeni nazw może mieć nazwę dowolnych elementów. clr-namespace Jednak wartości i assembly muszą być zgodne ze szczegółami kontrolki niestandardowej. Po zadeklarowaniu przestrzeni nazw prefiks jest używany do odwołwania się do komórki niestandardowej.
W poniższym przykładzie kodu pokazano, jak NativeCell można używać komórki niestandardowej na stronie języka 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;
}
...
}
Kontrolka Xamarin.FormsListView służy do wyświetlania listy danych, która jest wypełniana za pośrednictwem ItemSource właściwości . Strategia RecycleElement buforowania próbuje zminimalizować zużycie pamięci i szybkość ListView wykonywania przez odtworzenie komórek listy. Aby uzyskać więcej informacji, zobacz Strategia buforowania.
Każdy wiersz na liście zawiera trzy elementy danych — nazwę, kategorię i nazwę pliku obrazu. Układ każdego wiersza na liście jest definiowany przez DataTemplate przywoływaną ListView.ItemTemplate właściwość powiązaną. Definiuje DataTemplate , że każdy wiersz danych na liście będzie NativeCell zawierać jego Namewłaściwości , Categoryi ImageFilename za pomocą powiązania danych. Aby uzyskać więcej informacji na temat kontrolki ListView , zobacz ListView.
Niestandardowy moduł renderowania można teraz dodać do każdego projektu aplikacji, aby dostosować układ specyficzny dla platformy dla każdej komórki.
Tworzenie niestandardowego modułu renderowania na każdej platformie
Proces tworzenia niestandardowej klasy renderera jest następujący:
- Utwórz podklasę
ViewCellRendererklasy, która renderuje komórkę niestandardową. - Zastąpij metodę specyficzną dla platformy, która renderuje komórkę niestandardową i zapisuje logikę, aby ją dostosować.
ExportRendererDodaj atrybut do niestandardowej klasy renderera, aby określić, że będzie on używany do renderowania komórki niestandardowejXamarin.Forms. Ten atrybut służy do rejestrowania niestandardowego modułu renderowania za pomocą Xamarin.Formspolecenia .
Uwaga
W przypadku większości Xamarin.Forms elementów opcjonalne jest udostępnienie niestandardowego modułu renderowania w każdym projekcie platformy. Jeśli niestandardowy moduł renderowania nie jest zarejestrowany, zostanie użyty domyślny moduł renderowania dla klasy bazowej kontrolki. Jednak niestandardowe programy renderowania są wymagane w każdym projekcie platformy podczas renderowania elementu ViewCell .
Na poniższym diagramie przedstawiono obowiązki każdego projektu w przykładowej aplikacji wraz z relacjami między nimi:

Komórka niestandardowa NativeCell jest renderowana przez klasy renderera specyficzne dla platformy, które pochodzą z ViewCellRenderer klasy dla każdej platformy. Powoduje to renderowanie każdej NativeCell komórki niestandardowej z układem specyficznym dla platformy, jak pokazano na poniższych zrzutach ekranu:

Klasa ViewCellRenderer uwidacznia metody specyficzne dla platformy do renderowania komórki niestandardowej. Jest GetCell to metoda na platformie iOS, GetCellCore metoda na platformie Android i GetTemplate metoda w systemie UWP.
Każda niestandardowa klasa modułu renderowania jest ozdobiona atrybutem ExportRenderer , który rejestruje program renderujący za pomocą Xamarin.Formspolecenia . Atrybut przyjmuje dwa parametry — nazwę Xamarin.Forms typu renderowanej komórki i nazwę typu niestandardowego modułu renderowania. Prefiks assembly atrybutu określa, że atrybut ma zastosowanie do całego zestawu.
W poniższych sekcjach omówiono implementację poszczególnych niestandardowych klas renderer specyficznych dla platformy.
Tworzenie niestandardowego modułu renderowania w systemie iOS
Poniższy przykład kodu przedstawia niestandardowy moduł renderowania dla platformy 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;
}
...
}
}
Metoda jest wywoływana GetCell w celu skompilowania każdej komórki do wyświetlenia. Każda komórka jest wystąpieniem NativeiOSCell , które definiuje układ komórki i jej danych. Operacja GetCell metody jest zależna od ListView strategii buforowania:
ListViewGdy strategia buforowania toRetainElement,GetCellmetoda zostanie wywołana dla każdej komórki. WystąpienieNativeiOSCellzostanie utworzone dla każdegoNativeCellwystąpienia, które jest początkowo wyświetlane na ekranie. Gdy użytkownik przewijaListViewelement ,NativeiOSCellwystąpienia zostaną ponownie użyte. Aby uzyskać więcej informacji na temat ponownego użycia komórek systemu iOS, zobacz Ponowne używanie komórek.Uwaga
Ten niestandardowy kod modułu renderowania będzie ponownie używać niektórych komórek nawet wtedy, gdy właściwość jest ustawiona
ListViewna zachowanie komórek.Dane wyświetlane przez każde wystąpienie, niezależnie
NativeiOSCellod tego, czy nowo utworzone, czy ponownie używane, zostaną zaktualizowane przy użyciu danych z każdegoNativeCellwystąpienia za pomocąUpdateCellmetody .Uwaga
Metoda
OnNativeCellPropertyChangednigdy nie zostanie wywołana, gdyListViewstrategia buforowania zostanie ustawiona tak, aby zachować komórki.ListViewGdy strategia buforowania toRecycleElement,GetCellmetoda zostanie wywołana dla każdej komórki, która jest początkowo wyświetlana na ekranie. WystąpienieNativeiOSCellzostanie utworzone dla każdegoNativeCellwystąpienia, które jest początkowo wyświetlane na ekranie. Dane wyświetlane przez każdeNativeiOSCellwystąpienie zostaną zaktualizowane przy użyciu danych zNativeCellwystąpienia za pomocąUpdateCellmetody . Jednak metoda nie zostanie wywołana,GetCellgdy użytkownik przewijaListViewelement .NativeiOSCellZamiast tego wystąpienia zostaną ponownie użyte.PropertyChangedzdarzenia zostaną zgłoszone w wystąpieniuNativeCell, gdy zmienią się jego dane, aOnNativeCellPropertyChangedprogram obsługi zdarzeń zaktualizuje dane w każdym ponownie użytymNativeiOSCellwystąpieniu.
Poniższy przykład kodu przedstawia metodę OnNativeCellPropertyChanged wywoływaną podczas wywoływanego PropertyChanged zdarzenia:
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);
}
}
}
}
Ta metoda aktualizuje dane wyświetlane przez ponownie używane NativeiOSCell wystąpienia. Jest sprawdzana zmieniona właściwość, ponieważ metoda może być wywoływana wiele razy.
Klasa NativeiOSCell definiuje układ dla każdej komórki i jest wyświetlany w poniższym przykładzie kodu:
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);
}
}
Ta klasa definiuje kontrolki używane do renderowania zawartości komórki i ich układu. Klasa implementuje INativeElementView interfejs, który jest wymagany, gdy ListView używa RecycleElement strategii buforowania. Ten interfejs określa, że klasa musi zaimplementować Element właściwość, która powinna zwracać niestandardowe dane komórek dla komórek pochodzących z recyklingu.
Konstruktor NativeiOSCell inicjuje wygląd HeadingLabelwłaściwości , SubheadingLabeli CellImageView . Te właściwości są używane do wyświetlania danych przechowywanych w wystąpieniu NativeCell z UpdateCell wywoływaną metodą ustawiania wartości każdej właściwości. Ponadto w przypadku ListView użycia RecycleElement strategii buforowania dane wyświetlane przez HeadingLabelelement , SubheadingLabeli CellImageView właściwości mogą być aktualizowane przez metodę OnNativeCellPropertyChanged w niestandardowym module renderowania.
Układ komórek jest wykonywany przez LayoutSubviews przesłonięcia, które ustawia współrzędne HeadingLabel, SubheadingLabeli CellImageView w komórce.
Tworzenie niestandardowego modułu renderowania w systemie Android
W poniższym przykładzie kodu pokazano niestandardowy moduł renderowania dla platformy 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;
}
...
}
}
Metoda jest wywoływana GetCellCore w celu skompilowania każdej komórki do wyświetlenia. Każda komórka jest wystąpieniem NativeAndroidCell , które definiuje układ komórki i jej danych. Operacja GetCellCore metody jest zależna od ListView strategii buforowania:
ListViewGdy strategia buforowania toRetainElement,GetCellCoremetoda zostanie wywołana dla każdej komórki. ZostanieNativeAndroidCellutworzony dla każdegoNativeCellwystąpienia, które jest początkowo wyświetlane na ekranie. Gdy użytkownik przewijaListViewelement ,NativeAndroidCellwystąpienia zostaną ponownie użyte. Aby uzyskać więcej informacji na temat ponownego użycia komórek systemu Android, zobacz Temat Ponowne używanie widoku wiersza.Uwaga
Należy pamiętać, że ten niestandardowy kod modułu renderowania wykona ponowne użycie komórki nawet wtedy, gdy
ListViewustawiono opcję zachowywania komórek.Dane wyświetlane przez każde wystąpienie, niezależnie
NativeAndroidCellod tego, czy nowo utworzone, czy ponownie używane, zostaną zaktualizowane przy użyciu danych z każdegoNativeCellwystąpienia za pomocąUpdateCellmetody .Uwaga
Należy pamiętać, że podczas gdy
OnNativeCellPropertyChangedmetoda zostanie wywołana, gdyListViewwłaściwość zostanie ustawiona na zachowanie komórek, nieNativeAndroidCellzaktualizuje wartości właściwości.ListViewGdy strategia buforowania toRecycleElement,GetCellCoremetoda zostanie wywołana dla każdej komórki, która jest początkowo wyświetlana na ekranie. WystąpienieNativeAndroidCellzostanie utworzone dla każdegoNativeCellwystąpienia, które jest początkowo wyświetlane na ekranie. Dane wyświetlane przez każdeNativeAndroidCellwystąpienie zostaną zaktualizowane przy użyciu danych zNativeCellwystąpienia za pomocąUpdateCellmetody . Jednak metoda nie zostanie wywołana,GetCellCoregdy użytkownik przewijaListViewelement .NativeAndroidCellZamiast tego wystąpienia zostaną ponownie użyte.PropertyChangedzdarzenia zostaną zgłoszone w wystąpieniuNativeCell, gdy zmienią się jego dane, aOnNativeCellPropertyChangedprogram obsługi zdarzeń zaktualizuje dane w każdym ponownie użytymNativeAndroidCellwystąpieniu.
Poniższy przykład kodu przedstawia metodę OnNativeCellPropertyChanged wywoływaną podczas wywoływanego PropertyChanged zdarzenia:
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);
}
}
}
}
Ta metoda aktualizuje dane wyświetlane przez ponownie używane NativeAndroidCell wystąpienia. Jest sprawdzana zmieniona właściwość, ponieważ metoda może być wywoływana wiele razy.
Klasa NativeAndroidCell definiuje układ dla każdej komórki i jest wyświetlany w poniższym przykładzie kodu:
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);
}
}
}
Ta klasa definiuje kontrolki używane do renderowania zawartości komórki i ich układu. Klasa implementuje INativeElementView interfejs, który jest wymagany, gdy ListView używa RecycleElement strategii buforowania. Ten interfejs określa, że klasa musi zaimplementować Element właściwość, która powinna zwracać niestandardowe dane komórek dla komórek pochodzących z recyklingu.
Konstruktor NativeAndroidCell zawyża NativeAndroidCell układ i inicjuje HeadingTextViewwłaściwości , SubheadingTextViewi ImageView do kontrolek w zawyżonym układzie. Te właściwości są używane do wyświetlania danych przechowywanych w wystąpieniu NativeCell z UpdateCell wywoływaną metodą ustawiania wartości każdej właściwości. Ponadto w przypadku ListView użycia RecycleElement strategii buforowania dane wyświetlane przez HeadingTextViewelement , SubheadingTextViewi ImageView właściwości mogą być aktualizowane przez metodę OnNativeCellPropertyChanged w niestandardowym module renderowania.
Poniższy przykład kodu przedstawia definicję NativeAndroidCell.axml układu dla pliku układu:
<?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>
Ten układ określa, że dwie TextView kontrolki i kontrolka ImageView są używane do wyświetlania zawartości komórki. Te dwie TextView kontrolki są zorientowane w pionie w obrębie LinearLayout kontrolki, a wszystkie kontrolki znajdują się w obiekcie RelativeLayout.
Tworzenie niestandardowego modułu renderowania na platformie UWP
W poniższym przykładzie kodu pokazano niestandardowy moduł renderowania dla platformy 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;
}
}
}
Metoda GetTemplate jest wywoływana w celu zwrócenia komórki do renderowania dla każdego wiersza danych na liście. Tworzy dla DataTemplate każdego NativeCell wystąpienia, które będzie wyświetlane na ekranie z DataTemplate definiowaniem wyglądu i zawartości komórki.
Element DataTemplate jest przechowywany w słowniku zasobów na poziomie aplikacji i jest wyświetlany w poniższym przykładzie kodu:
<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>
Określa DataTemplate kontrolki używane do wyświetlania zawartości komórki oraz ich układu i wyglądu. Dwie TextBlock kontrolki i kontrolka Image są używane do wyświetlania zawartości komórki za pomocą powiązania danych. Ponadto wystąpienie obiektu ConcatImageExtensionConverter służy do łączenia .jpg rozszerzenia pliku z każdą nazwą pliku obrazu. Dzięki temu kontrolka Image może ładować i renderować obraz po ustawieniu jej Source właściwości.
Podsumowanie
W tym artykule pokazano, jak utworzyć niestandardowy moduł renderujący dla kontrolki ViewCell hostowanej w kontrolce Xamarin.FormsListView . Xamarin.Forms Uniemożliwia to wielokrotne wywoływanie obliczeń układu podczas ListView przewijania.