Přizpůsobení zobrazení ListView
ListView Xamarin.Forms je zobrazení, které zobrazuje kolekci dat jako svislý seznam. Tento článek ukazuje, jak vytvořit vlastní renderer, který zapouzdřuje ovládací prvky seznamu specifické pro platformu a nativní rozložení buněk, což umožňuje větší kontrolu nad výkonem řízení nativních seznamů.
Každé Xamarin.Forms zobrazení má doprovodný renderer pro každou platformu, která vytvoří instanci nativního ovládacího prvku. ListView
Při vykreslení Xamarin.Forms aplikací se v iOSu ListViewRenderer
vytvoří instance třídy, která následně vytvoří instanci nativního UITableView
ovládacího prvku. Na platformě Android třída ListViewRenderer
vytvoří instanci nativního ListView
ovládacího prvku. V Univerzální platforma Windows (UPW) třída ListViewRenderer
vytvoří instanci nativního ListView
ovládacího prvku. Další informace o rendereru a nativních tříd ovládacích prvcích, které Xamarin.Forms řídí mapování, naleznete v tématu Renderer Základní třídy a nativní ovládací prvky.
Následující diagram znázorňuje vztah mezi ovládacím ListView
prvku a odpovídajícími nativními ovládacími prvky, které ho implementují:
Proces vykreslování můžete využít k implementaci přizpůsobení specifických pro platformu vytvořením vlastního rendereru pro každou platformu ListView
. Postup je následující:
- Vytvořte Xamarin.Forms vlastní ovládací prvek.
- Využití vlastního ovládacího prvku z Xamarin.Forms.
- Vytvořte vlastní renderer pro ovládací prvek na každé platformě.
Jednotlivé položky budou nyní popsány a implementují NativeListView
renderer, který využívá ovládací prvky seznamu specifické pro platformu a nativní rozložení buněk. Tento scénář je užitečný při přenosu existující nativní aplikace, která obsahuje seznam a kód buňky, které je možné znovu použít. Kromě toho umožňuje podrobné přizpůsobení funkcí ovládacích prvků seznamu, které můžou ovlivnit výkon, jako je virtualizace dat.
Vytvoření vlastního ovládacího prvku ListView
Vlastní ListView
ovládací prvek lze vytvořit podtřídou ListView
třídy, jak je znázorněno v následujícím příkladu kódu:
public class NativeListView : ListView
{
public static readonly BindableProperty ItemsProperty =
BindableProperty.Create ("Items", typeof(IEnumerable<DataSource>), typeof(NativeListView), new List<DataSource> ());
public IEnumerable<DataSource> Items {
get { return (IEnumerable<DataSource>)GetValue (ItemsProperty); }
set { SetValue (ItemsProperty, value); }
}
public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
public void NotifyItemSelected (object item)
{
if (ItemSelected != null) {
ItemSelected (this, new SelectedItemChangedEventArgs (item));
}
}
}
Vytvoří se NativeListView
v projektu knihovny .NET Standard a definuje rozhraní API pro vlastní ovládací prvek. Tento ovládací prvek zveřejňuje Items
vlastnost, která se používá k naplnění ListView
daty a která mohou být vázána na účely zobrazení. Také zveřejňuje ItemSelected
událost, která se aktivuje při každém výběru položky v ovládacím prvku nativního seznamu specifického pro platformu. Další informace o datové vazbě najdete v tématu Základy datových vazeb.
Využívání vlastního ovládacího prvku
Na NativeListView
vlastní ovládací prvek lze odkazovat v xaml v projektu knihovny .NET Standard deklarováním oboru názvů pro jeho umístění a použitím předpony oboru názvů v ovládacím prvku. Následující příklad kódu ukazuje, jak NativeListView
může vlastní ovládací prvek využívat stránka XAML:
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
...>
...
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="{x:Static local:App.Description}" HorizontalTextAlignment="Center" />
<local:NativeListView Grid.Row="1" x:Name="nativeListView" ItemSelected="OnItemSelected" VerticalOptions="FillAndExpand" />
</Grid>
</ContentPage.Content>
</ContentPage>
Předponu local
oboru názvů lze pojmenovat cokoli. clr-namespace
Hodnoty ale assembly
musí odpovídat podrobnostem vlastního ovládacího prvku. Jakmile je obor názvů deklarován, předpona se použije k odkazování na vlastní ovládací prvek.
Následující příklad kódu ukazuje, jak NativeListView
může vlastní ovládací prvek využívat stránka jazyka C#:
public class MainPageCS : ContentPage
{
NativeListView nativeListView;
public MainPageCS()
{
nativeListView = new NativeListView
{
Items = DataSource.GetList(),
VerticalOptions = LayoutOptions.FillAndExpand
};
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 Grid
{
RowDefinitions = {
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = new GridLength (1, GridUnitType.Star) }
},
Children = {
new Label { Text = App.Description, HorizontalTextAlignment = TextAlignment.Center },
nativeListView
}
};
nativeListView.ItemSelected += OnItemSelected;
}
...
}
Vlastní NativeListView
ovládací prvek používá vlastní vykreslovací moduly specifické pro platformu k zobrazení seznamu dat, která jsou naplněna vlastností Items
. Každý řádek v seznamu obsahuje tři položky dat – název, kategorii a název souboru obrázku. Rozložení jednotlivých řádků v seznamu je definováno vlastním vykreslovacím modulem pro konkrétní platformu.
Poznámka:
Vzhledem k tomu, že NativeListView
vlastní ovládací prvek bude vykreslen pomocí ovládacích prvků seznamu specifických pro platformu, které zahrnují možnost posouvání, by vlastní ovládací prvek neměl být hostován v posouvatelných ovládacích prvcích rozložení, jako je například ScrollView
.
Do každého projektu aplikace je teď možné přidat vlastní renderer, který vytvoří ovládací prvky seznamu specifické pro platformu a nativní rozložení buněk.
Vytvoření vlastního rendereru na jednotlivých platformách
Proces vytvoření vlastní třídy rendereru je následující:
- Vytvořte podtřídu
ListViewRenderer
třídy, která vykreslí vlastní ovládací prvek. - Přepište metodu
OnElementChanged
, která vykreslí vlastní ovládací prvek a zapisuje logiku pro přizpůsobení. Tato metoda se volá při vytvoření odpovídající Xamarin.FormsListView
metody. - Přidejte do vlastní třídy rendereru
ExportRenderer
atribut, který určí, že se použije k vykreslení vlastního Xamarin.Forms ovládacího prvku. Tento atribut se používá k registraci vlastního rendereru v Xamarin.Forms.
Poznámka:
V každém projektu platformy je volitelné zadat vlastní renderer. Pokud není zaregistrovaný vlastní renderer, použije se výchozí renderer základní třídy buňky.
Následující diagram znázorňuje zodpovědnosti jednotlivých projektů v ukázkové aplikaci spolu s relacemi mezi nimi:
Vlastní NativeListView
ovládací prvek se vykresluje pomocí tříd rendereru specifických pro platformu, které jsou odvozeny od třídy pro každou platformu ListViewRenderer
. Výsledkem je vykreslení každého NativeListView
vlastního ovládacího prvku pomocí ovládacích prvků seznamu specifických pro platformu a rozložení nativních buněk, jak je znázorněno na následujících snímcích obrazovky:
Třída ListViewRenderer
zveřejňuje metodu OnElementChanged
, která je volána při Xamarin.Forms vytvoření vlastního ovládacího prvku pro vykreslení odpovídajícího nativního ovládacího prvku. Tato metoda přebírá ElementChangedEventArgs
parametr, který obsahuje OldElement
a NewElement
vlastnosti. Tyto vlastnosti představují Xamarin.Forms prvek, ke kterému byl renderer připojen, a Xamarin.Forms prvek, ke kterému je renderer připojen, v uvedeném pořadí. V ukázkové aplikaci OldElement
bude vlastnost a NewElement
vlastnost bude obsahovat odkaz na NativeListView
null
instanci.
Přepsáná verze OnElementChanged
metody v každé třídě rendereru specifické pro platformu je místo pro provedení přizpůsobení nativního ovládacího prvku. Typový odkaz na nativní ovládací prvek, který se používá na platformě, je přístupný prostřednictvím Control
vlastnosti. Kromě toho lze prostřednictvím vlastnosti získat Element
odkaz na Xamarin.Forms vykreslovaný ovládací prvek.
Při přihlášení k odběru obslužných rutin událostí v OnElementChanged
metodě je potřeba věnovat pozornost, jak je znázorněno v následujícím příkladu kódu:
protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged (e);
if (e.OldElement != null) {
// Unsubscribe from event handlers and cleanup any resources
}
if (e.NewElement != null) {
// Configure the native control and subscribe to event handlers
}
}
Nativní ovládací prvek by měl být nakonfigurovaný a obslužné rutiny událostí odebírané pouze při připojení vlastního rendereru k novému Xamarin.Forms prvku. Podobně by se měly všechny obslužné rutiny událostí, které byly přihlášeny k odběru, odhlásit pouze v případě, že je prvek, který renderer připojí ke změnám. Přijetí tohoto přístupu vám pomůže vytvořit vlastní renderer, který netrpí nevracením paměti.
Přepsáná verze OnElementPropertyChanged
metody, v každé třídě rendereru specifické pro platformu, je místo, kde reagovat na změny vazby vlastností ve vlastním ovládacím Xamarin.Forms prvku. Kontrola změněné vlastnosti by měla být vždy provedena, protože toto přepsání lze volat mnohokrát.
Každá vlastní třída rendereru je zdobena ExportRenderer
atributem, který registruje renderer s Xamarin.Forms. Atribut má dva parametry – název typu vykreslovaného vlastního Xamarin.Forms ovládacího prvku a název typu vlastního rendereru. Předpona assembly
atributu určuje, že atribut se vztahuje na celé sestavení.
Následující části se týkají implementace jednotlivých vlastních tříd rendereru specifických pro platformu.
Vytvoření vlastního rendereru v iOSu
Následující příklad kódu ukazuje vlastní renderer pro platformu iOS:
[assembly: ExportRenderer (typeof(NativeListView), typeof(NativeiOSListViewRenderer))]
namespace CustomRenderer.iOS
{
public class NativeiOSListViewRenderer : ListViewRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged (e);
if (e.OldElement != null) {
// Unsubscribe
}
if (e.NewElement != null) {
Control.Source = new NativeiOSListViewSource (e.NewElement as NativeListView);
}
}
}
}
Ovládací UITableView
prvek je nakonfigurován vytvořením instance NativeiOSListViewSource
třídy za předpokladu, že vlastní renderer je připojen k novému Xamarin.Forms prvku. Tato třída poskytuje data ovládacímu UITableView
prvku přepsáním RowsInSection
a GetCell
metodami z UITableViewSource
třídy a zveřejněním Items
vlastnosti, která obsahuje seznam dat, která se mají zobrazit. Třída také poskytuje přepsání RowSelected
metody, která vyvolá ItemSelected
událost poskytovanou vlastním ovládacím NativeListView
prvku. Další informace o přepsání metody naleznete v části Podtřídy UITableViewSource. Metoda GetCell
vrátí UITableCellView
data naplněná daty pro každý řádek v seznamu a je zobrazena v následujícím příkladu kódu:
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
// request a recycled cell to save memory
NativeiOSListViewCell cell = tableView.DequeueReusableCell (cellIdentifier) as NativeiOSListViewCell;
// if there are no cells to reuse, create a new one
if (cell == null) {
cell = new NativeiOSListViewCell (cellIdentifier);
}
if (String.IsNullOrWhiteSpace (tableItems [indexPath.Row].ImageFilename)) {
cell.UpdateCell (tableItems [indexPath.Row].Name
, tableItems [indexPath.Row].Category
, null);
} else {
cell.UpdateCell (tableItems [indexPath.Row].Name
, tableItems [indexPath.Row].Category
, UIImage.FromFile ("Images/" + tableItems [indexPath.Row].ImageFilename + ".jpg"));
}
return cell;
}
Tato metoda vytvoří NativeiOSListViewCell
instanci pro každý řádek dat, který se zobrazí na obrazovce. Instance NativeiOSCell
definuje rozložení jednotlivých buněk a dat buňky. Když buňka zmizí z obrazovky kvůli posouvání, bude buňka k dispozici pro opakované použití. Tím se zabrání plýtvání paměti tím, že zajistíte, aby se na obrazovce zobrazovaly pouze NativeiOSCell
instance dat, a ne všechna data v seznamu. Další informace o opětovném použití buňky naleznete v tématu Opětovné použití buňky. Metoda GetCell
také přečte ImageFilename
vlastnost každého řádku dat, za předpokladu, že existuje, a přečte image a uloží ji jako UIImage
instanci před aktualizací NativeiOSListViewCell
instance s daty (název, kategorie a obrázek) řádku.
Třída NativeiOSListViewCell
definuje rozložení pro každou buňku a je znázorněna v následujícím příkladu kódu:
public class NativeiOSListViewCell : UITableViewCell
{
UILabel headingLabel, subheadingLabel;
UIImageView imageView;
public NativeiOSListViewCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.FromRGB (218, 255, 127);
imageView = 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 (imageView);
}
public void UpdateCell (string caption, string subtitle, UIImage image)
{
headingLabel.Text = caption;
subheadingLabel.Text = subtitle;
imageView.Image = image;
}
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
headingLabel.Frame = new CoreGraphics.CGRect (5, 4, ContentView.Bounds.Width - 63, 25);
subheadingLabel.Frame = new CoreGraphics.CGRect (100, 18, 100, 20);
imageView.Frame = new CoreGraphics.CGRect (ContentView.Bounds.Width - 63, 5, 33, 33);
}
}
Tato třída definuje ovládací prvky použité k vykreslení obsahu buňky a jejich rozložení. Konstruktor NativeiOSListViewCell
vytvoří instance UILabel
a UIImageView
ovládací prvky a inicializuje jejich vzhled. Tyto ovládací prvky slouží k zobrazení dat jednotlivých řádků s metodou použitou UpdateCell
k nastavení těchto dat v UILabel
instancích a UIImageView
instancích. Umístění těchto instancí je nastaveno přepsánou LayoutSubviews
metodou zadáním jejich souřadnic v buňce.
Reakce na změnu vlastnosti vlastního ovládacího prvku
Pokud se NativeListView.Items
vlastnost změní z důvodu přidání nebo odebrání položek ze seznamu, vlastní renderer musí reagovat zobrazením změn. Toho lze dosáhnout přepsáním OnElementPropertyChanged
metody, která je znázorněna v následujícím příkladu kódu:
protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged (sender, e);
if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) {
Control.Source = new NativeiOSListViewSource (Element as NativeListView);
}
}
Metoda vytvoří novou instanci NativeiOSListViewSource
třídy, která poskytuje data ovládacímu UITableView
prvku za předpokladu, že se změnila vlastnost bindable NativeListView.Items
.
Vytvoření vlastního rendereru v Androidu
Následující příklad kódu ukazuje vlastní renderer pro platformu Android:
[assembly: ExportRenderer(typeof(NativeListView), typeof(NativeAndroidListViewRenderer))]
namespace CustomRenderer.Droid
{
public class NativeAndroidListViewRenderer : ListViewRenderer
{
Context _context;
public NativeAndroidListViewRenderer(Context context) : base(context)
{
_context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// unsubscribe
Control.ItemClick -= OnItemClick;
}
if (e.NewElement != null)
{
// subscribe
Control.Adapter = new NativeAndroidListViewAdapter(_context as Android.App.Activity, e.NewElement as NativeListView);
Control.ItemClick += OnItemClick;
}
}
...
void OnItemClick(object sender, Android.Widget.AdapterView.ItemClickEventArgs e)
{
((NativeListView)Element).NotifyItemSelected(((NativeListView)Element).Items.ToList()[e.Position - 1]);
}
}
}
ListView
Nativní ovládací prvek je nakonfigurován za předpokladu, že vlastní renderer je připojen k novému Xamarin.Forms prvku. Tato konfigurace zahrnuje vytvoření instance NativeAndroidListViewAdapter
třídy, která poskytuje data nativnímu ListView
ovládacímu prvku, a registraci obslužné rutiny události ke zpracování ItemClick
události. Tato obslužná rutina pak vyvolá ItemSelected
událost poskytovanou vlastním ovládacím NativeListView
prvku. Událost ItemClick
se odhlásí, pokud Xamarin.Forms je prvek, který renderer připojí ke změnám.
Odvozuje NativeAndroidListViewAdapter
z BaseAdapter
třídy a zveřejňuje Items
vlastnost, která obsahuje seznam dat, která mají být zobrazena, a také přepsání Count
, , GetView
GetItemId
a this[int]
metody. Další informace o těchto přepsání metody naleznete v tématu Implementace ListAdapter. Metoda GetView
vrátí zobrazení pro každý řádek naplněný daty a je znázorněn v následujícím příkladu kódu:
public override View GetView (int position, View convertView, ViewGroup parent)
{
var item = tableItems [position];
var view = convertView;
if (view == null) {
// no view to re-use, create new
view = context.LayoutInflater.Inflate (Resource.Layout.NativeAndroidListViewCell, null);
}
view.FindViewById<TextView> (Resource.Id.Text1).Text = item.Name;
view.FindViewById<TextView> (Resource.Id.Text2).Text = item.Category;
// grab the old image and dispose of it
if (view.FindViewById<ImageView> (Resource.Id.Image).Drawable != null) {
using (var image = view.FindViewById<ImageView> (Resource.Id.Image).Drawable as BitmapDrawable) {
if (image != null) {
if (image.Bitmap != null) {
//image.Bitmap.Recycle ();
image.Bitmap.Dispose ();
}
}
}
}
// If a new image is required, display it
if (!String.IsNullOrWhiteSpace (item.ImageFilename)) {
context.Resources.GetBitmapAsync (item.ImageFilename).ContinueWith ((t) => {
var bitmap = t.Result;
if (bitmap != null) {
view.FindViewById<ImageView> (Resource.Id.Image).SetImageBitmap (bitmap);
bitmap.Dispose ();
}
}, TaskScheduler.FromCurrentSynchronizationContext ());
} else {
// clear the image
view.FindViewById<ImageView> (Resource.Id.Image).SetImageBitmap (null);
}
return view;
}
Metoda GetView
je volána k vrácení buňky, která se má vykreslit, jako a View
pro každý řádek dat v seznamu. Vytvoří View
instanci pro každý řádek dat, která se zobrazí na obrazovce, s vzhledem View
instance, která je definována v souboru rozložení. Když buňka zmizí z obrazovky kvůli posouvání, bude buňka k dispozici pro opakované použití. Tím se zabrání plýtvání paměti tím, že zajistíte, aby se na obrazovce zobrazovaly pouze View
instance dat, a ne všechna data v seznamu. Další informace o opětovném použití zobrazení najdete v tématu Opětovné použití zobrazení řádků.
Metoda GetView
také naplní View
instanci daty, včetně čtení dat obrázku z názvu souboru zadaného ImageFilename
ve vlastnosti.
Rozložení každé buňky dispayed podle nativní ListView
je definováno v NativeAndroidListViewCell.axml
souboru rozložení, který je nafoukl metodou LayoutInflater.Inflate
. Následující příklad kódu ukazuje definici rozložení:
<?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/Text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF7F3300"
android:textSize="20dip"
android:textStyle="italic" />
<TextView
android:id="@+id/Text2"
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>
Toto rozložení určuje, že se k zobrazení obsahu buňky používají dva TextView
ovládací prvky a ImageView
ovládací prvek. Tyto dva TextView
ovládací prvky jsou svisle orientované v LinearLayout
rámci ovládacího prvku, přičemž všechny ovládací prvky obsažené v objektu RelativeLayout
.
Reakce na změnu vlastnosti vlastního ovládacího prvku
Pokud se NativeListView.Items
vlastnost změní z důvodu přidání nebo odebrání položek ze seznamu, vlastní renderer musí reagovat zobrazením změn. Toho lze dosáhnout přepsáním OnElementPropertyChanged
metody, která je znázorněna v následujícím příkladu kódu:
protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged (sender, e);
if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) {
Control.Adapter = new NativeAndroidListViewAdapter (_context as Android.App.Activity, Element as NativeListView);
}
}
Metoda vytvoří novou instanci NativeAndroidListViewAdapter
třídy, která poskytuje data nativnímu ListView
ovládacímu prvku za předpokladu, že se změnila vlastnost bindable NativeListView.Items
.
Vytvoření vlastního rendereru v UPW
Následující příklad kódu ukazuje vlastní renderer pro UPW:
[assembly: ExportRenderer(typeof(NativeListView), typeof(NativeUWPListViewRenderer))]
namespace CustomRenderer.UWP
{
public class NativeUWPListViewRenderer : ListViewRenderer
{
ListView listView;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged(e);
listView = Control as ListView;
if (e.OldElement != null)
{
// Unsubscribe
listView.SelectionChanged -= OnSelectedItemChanged;
}
if (e.NewElement != null)
{
listView.SelectionMode = ListViewSelectionMode.Single;
listView.IsItemClickEnabled = false;
listView.ItemsSource = ((NativeListView)e.NewElement).Items;
listView.ItemTemplate = App.Current.Resources["ListViewItemTemplate"] as Windows.UI.Xaml.DataTemplate;
// Subscribe
listView.SelectionChanged += OnSelectedItemChanged;
}
}
void OnSelectedItemChanged(object sender, SelectionChangedEventArgs e)
{
((NativeListView)Element).NotifyItemSelected(listView.SelectedItem);
}
}
}
ListView
Nativní ovládací prvek je nakonfigurován za předpokladu, že vlastní renderer je připojen k novému Xamarin.Forms prvku. Tato konfigurace zahrnuje nastavení, jakým způsobem bude nativní ListView
ovládací prvek reagovat na vybrané položky, naplnění dat zobrazených ovládacím prvku, definování vzhledu a obsahu každé buňky a registraci obslužné rutiny události ke zpracování SelectionChanged
události. Tato obslužná rutina pak vyvolá ItemSelected
událost poskytovanou vlastním ovládacím NativeListView
prvku. Událost SelectionChanged
se odhlásí, pokud Xamarin.Forms je prvek, který renderer připojí ke změnám.
Vzhled a obsah každé nativní ListView
buňky jsou definovány DataTemplate
názvem ListViewItemTemplate
. Toto DataTemplate
je uloženo ve slovníku prostředků na úrovni aplikace a je znázorněno v následujícím příkladu kódu:
<DataTemplate x:Key="ListViewItemTemplate">
<Grid Background="#DAFF7F">
<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>
Určuje DataTemplate
ovládací prvky použité k zobrazení obsahu buňky a jejich rozložení a vzhledu. Dva TextBlock
ovládací prvky a Image
ovládací prvek slouží k zobrazení obsahu buňky prostřednictvím datové vazby. Kromě toho se instance souboru ConcatImageExtensionConverter
používá ke zřetězení přípony .jpg
souboru pro každý název souboru obrázku. Tím se zajistí, že Image
ovládací prvek může načíst a vykreslit obrázek, když je nastavena Source
jeho vlastnost.
Reakce na změnu vlastnosti vlastního ovládacího prvku
Pokud se NativeListView.Items
vlastnost změní z důvodu přidání nebo odebrání položek ze seznamu, vlastní renderer musí reagovat zobrazením změn. Toho lze dosáhnout přepsáním OnElementPropertyChanged
metody, která je znázorněna v následujícím příkladu kódu:
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == NativeListView.ItemsProperty.PropertyName)
{
listView.ItemsSource = ((NativeListView)Element).Items;
}
}
Metoda znovu naplní nativní ListView
ovládací prvek změněnými daty za předpokladu, že se změnila vlastnost bindable NativeListView.Items
.
Shrnutí
Tento článek ukázal, jak vytvořit vlastní renderer, který zapouzdřuje ovládací prvky seznamu specifické pro platformu a nativní rozložení buněk, což umožňuje větší kontrolu nad výkonem řízení nativních seznamů.