Bagikan melalui


Mengkustomisasi ListView

Xamarin.Forms ListView adalah tampilan yang menampilkan kumpulan data sebagai daftar vertikal. Artikel ini menunjukkan cara membuat perender kustom yang merangkum kontrol daftar khusus platform dan tata letak sel asli, memungkinkan kontrol lebih besar atas performa kontrol daftar asli.

Setiap Xamarin.Forms tampilan memiliki perender yang menyertainya untuk setiap platform yang membuat instans kontrol asli. ListView Ketika dirender oleh Xamarin.Forms aplikasi, di iOS ListViewRenderer kelas dibuat, yang pada gilirannya membuat instans kontrol asliUITableView. Pada platform Android, ListViewRenderer kelas membuat instans kontrol asli ListView . Pada Platform Windows Universal (UWP), ListViewRenderer kelas membuat instans kontrol asliListView. Untuk informasi selengkapnya tentang kelas perender dan kontrol asli yang Xamarin.Forms mengontrol peta ke, lihat Kelas Dasar Perender dan Kontrol Asli.

Diagram berikut mengilustrasikan hubungan antara ListView kontrol dan kontrol asli terkait yang mengimplementasikannya:

Hubungan Antara Kontrol ListView dan Implementasi Kontrol Asli

Proses penyajian dapat dimanfaatkan untuk menerapkan penyesuaian khusus platform dengan membuat perender kustom untuk ListView di setiap platform. Proses untuk melakukan ini adalah sebagai berikut:

  1. BuatXamarin.Forms kontrol kustom.
  2. Gunakan kontrol kustom dari Xamarin.Forms.
  3. Buat perender kustom untuk kontrol pada setiap platform.

Setiap item sekarang akan dibahas pada gilirannya, untuk mengimplementasikan perender NativeListView yang memanfaatkan kontrol daftar khusus platform dan tata letak sel asli. Skenario ini berguna saat memindahkan aplikasi asli yang ada yang berisi daftar dan kode sel yang dapat digunakan kembali. Selain itu, ini memungkinkan penyesuaian terperinci fitur kontrol daftar yang dapat memengaruhi performa, seperti virtualisasi data.

Membuat Kontrol Tampilan Daftar Kustom

Kontrol kustom ListView dapat dibuat dengan mensubkelas ListView kelas, seperti yang ditunjukkan dalam contoh kode berikut:

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));
    }
  }
}

NativeListView dibuat dalam proyek pustaka .NET Standard dan menentukan API untuk kontrol kustom. Kontrol ini mengekspos Items properti yang digunakan untuk mengisi ListView dengan data, dan yang dapat diikat data untuk tujuan tampilan. Ini juga mengekspos ItemSelected peristiwa yang akan ditembakkan setiap kali item dipilih dalam kontrol daftar asli khusus platform. Untuk informasi selengkapnya tentang pengikatan data, lihat Dasar-Dasar Pengikatan Data.

Mengonsumsi Kontrol Kustom

NativeListView Kontrol kustom dapat direferensikan dalam Xaml dalam proyek pustaka Standar .NET dengan mendeklarasikan namespace untuk lokasinya dan menggunakan awalan namespace pada kontrol. Contoh kode berikut menunjukkan bagaimana NativeListView kontrol kustom dapat digunakan oleh halaman 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>

local Awalan namespace dapat diberi nama apa pun. Namun, clr-namespace nilai dan assembly harus cocok dengan detail kontrol kustom. Setelah namespace dinyatakan, awalan digunakan untuk mereferensikan kontrol kustom.

Contoh kode berikut menunjukkan bagaimana NativeListView kontrol kustom dapat dikonsumsi oleh halaman 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;
    }
    ...
}

NativeListView Kontrol kustom menggunakan perender kustom khusus platform untuk menampilkan daftar data, yang diisi melalui Items properti . Setiap baris dalam daftar berisi tiga item data – nama, kategori, dan nama file gambar. Tata letak setiap baris dalam daftar ditentukan oleh perender kustom khusus platform.

Catatan

NativeListView Karena kontrol kustom akan dirender menggunakan kontrol daftar khusus platform yang mencakup kemampuan gulir, kontrol kustom tidak boleh dihosting dalam kontrol tata letak yang dapat digulir seperti ScrollView.

Perender kustom sekarang dapat ditambahkan ke setiap proyek aplikasi untuk membuat kontrol daftar khusus platform dan tata letak sel asli.

Membuat Perender Kustom di setiap Platform

Proses untuk membuat kelas perender kustom adalah sebagai berikut:

  1. Buat subkelas ListViewRenderer kelas yang merender kontrol kustom.
  2. Ambil alih OnElementChanged metode yang merender kontrol kustom dan logika tulis untuk menyesuaikannya. Metode ini dipanggil ketika yang Xamarin.FormsListView sesuai dibuat.
  3. ExportRenderer Tambahkan atribut ke kelas perender kustom untuk menentukan bahwa atribut tersebut akan digunakan untuk merender Xamarin.Forms kontrol kustom. Atribut ini digunakan untuk mendaftarkan perender kustom dengan Xamarin.Forms.

Catatan

Ini bersifat opsional untuk menyediakan perender kustom di setiap proyek platform. Jika perender kustom tidak terdaftar, maka perender default untuk kelas dasar sel akan digunakan.

Diagram berikut mengilustrasikan tanggung jawab setiap proyek dalam aplikasi sampel, bersama dengan hubungan di antara mereka:

NativeListView Tanggung Jawab Proyek Perender Kustom

NativeListView Kontrol kustom dirender oleh kelas perender khusus platform, yang semuanya berasal dari ListViewRenderer kelas untuk setiap platform. Ini menghasilkan setiap NativeListView kontrol kustom yang dirender dengan kontrol daftar khusus platform dan tata letak sel asli, seperti yang ditunjukkan pada cuplikan layar berikut:

NativeListView di setiap Platform

Kelas ListViewRenderer mengekspos OnElementChanged metode , yang dipanggil ketika Xamarin.Forms kontrol kustom dibuat untuk merender kontrol asli yang sesuai. Metode ini mengambil ElementChangedEventArgs parameter, yang berisi OldElement properti dan NewElement . Properti ini mewakili Xamarin.Forms elemen tempat perender dilampirkan, dan Xamarin.Forms elemen yang dilampirkan oleh perender. Dalam aplikasi sampel, OldElement properti akan menjadi null dan NewElement properti akan berisi referensi ke NativeListView instans.

Versi OnElementChanged metode yang ditimpa, di setiap kelas perender khusus platform, adalah tempat untuk melakukan penyesuaian kontrol asli. Referensi yang diketik ke kontrol asli yang digunakan pada platform dapat diakses melalui Control properti . Selain itu, referensi ke Xamarin.Forms kontrol yang sedang dirender dapat diperoleh melalui Element properti .

Perawatan harus diambil saat berlangganan penanganan aktivitas dalam OnElementChanged metode , seperti yang ditunjukkan dalam contoh kode berikut:

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
  }
}

Kontrol asli hanya boleh dikonfigurasi dan penanganan aktivitas berlangganan ketika perender kustom dilampirkan ke elemen baru Xamarin.Forms . Demikian pula, setiap penanganan aktivitas yang berlangganan harus dihentikan langganannya hanya ketika elemen perender dilampirkan ke perubahan. Mengadopsi pendekatan ini akan membantu membuat perender kustom yang tidak menderita kebocoran memori.

Versi penggantian OnElementPropertyChanged metode, di setiap kelas perender khusus platform, adalah tempat untuk menanggapi perubahan properti yang dapat diikat pada Xamarin.Forms kontrol kustom. Pemeriksaan properti yang diubah harus selalu dilakukan, karena penimpaan ini dapat dipanggil berkali-kali.

Setiap kelas perender kustom dihiasi dengan ExportRenderer atribut yang mendaftarkan perender dengan Xamarin.Forms. Atribut mengambil dua parameter – nama jenis kontrol kustom yang Xamarin.Forms dirender, dan nama jenis perender kustom. assembly Awalan ke atribut menentukan bahwa atribut berlaku untuk seluruh rakitan.

Bagian berikut membahas implementasi setiap kelas perender kustom khusus platform.

Membuat Perender Kustom di iOS

Contoh kode berikut menunjukkan perender kustom untuk platform 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);
            }
        }
    }
}

UITableView Kontrol dikonfigurasi dengan membuat instans NativeiOSListViewSource kelas, asalkan perender kustom dilampirkan ke elemen baruXamarin.Forms. Kelas ini menyediakan data ke UITableView kontrol dengan mengambil alih RowsInSection metode dan GetCell dari UITableViewSource kelas, dan dengan mengekspos Items properti yang berisi daftar data yang akan ditampilkan. Kelas ini juga menyediakan RowSelected penimpaan metode yang memanggil ItemSelected peristiwa yang disediakan oleh NativeListView kontrol kustom. Untuk informasi selengkapnya tentang penimpaan metode, lihat Subkelas UITableViewSource. Metode mengembalikan GetCellUITableCellView yang diisi dengan data untuk setiap baris dalam daftar, dan diperlihatkan dalam contoh kode berikut:

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;
}

Metode ini membuat instans NativeiOSListViewCell untuk setiap baris data yang akan ditampilkan di layar. NativeiOSCell Instans menentukan tata letak setiap sel dan data sel. Saat sel menghilang dari layar karena menggulir, sel akan tersedia untuk digunakan kembali. Ini menghindari pemborosan memori dengan memastikan bahwa hanya NativeiOSCell ada instans untuk data yang ditampilkan di layar, bukan semua data dalam daftar. Untuk informasi selengkapnya tentang penggunaan kembali sel, lihat Penggunaan Kembali Sel. Metode ini GetCell juga membaca ImageFilename properti dari setiap baris data, asalkan ada, dan membaca gambar dan menyimpannya sebagai UIImage instans, sebelum memperbarui NativeiOSListViewCell instans dengan data (nama, kategori, dan gambar) untuk baris.

Kelas NativeiOSListViewCell menentukan tata letak untuk setiap sel, dan diperlihatkan dalam contoh kode berikut:

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);
  }
}

Kelas ini mendefinisikan kontrol yang digunakan untuk merender konten sel, dan tata letaknya. NativeiOSListViewCell Konstruktor membuat instans UILabel dan UIImageView kontrol, dan menginisialisasi tampilannya. Kontrol ini digunakan untuk menampilkan data setiap baris, dengan metode yang UpdateCell digunakan untuk mengatur data ini pada UILabel instans dan UIImageView . Lokasi instans ini diatur oleh metode yang ditimpa LayoutSubviews , dengan menentukan koordinatnya dalam sel.

Menanggapi Perubahan Properti pada Kontrol Kustom

NativeListView.Items Jika properti berubah, karena item ditambahkan ke atau dihapus dari daftar, perender kustom perlu merespons dengan menampilkan perubahan. Ini dapat dicapai dengan mengambil OnElementPropertyChanged alih metode , yang ditunjukkan dalam contoh kode berikut:

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);
  }
}

Metode ini membuat instans NativeiOSListViewSource baru kelas yang menyediakan data ke UITableView kontrol, asalkan properti yang dapat diikat NativeListView.Items telah berubah.

Membuat Custom Renderer di Android

Contoh kode berikut menunjukkan perender kustom untuk platform 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]);
        }
    }
}

Kontrol asli ListView dikonfigurasi asalkan perender kustom dilampirkan ke elemen baru Xamarin.Forms . Konfigurasi ini melibatkan pembuatan instans NativeAndroidListViewAdapter kelas yang menyediakan data ke kontrol asli ListView , dan mendaftarkan penanganan aktivitas untuk memproses ItemClick peristiwa. Pada gilirannya, handler ini akan memanggil peristiwa yang ItemSelected disediakan oleh NativeListView kontrol kustom. Peristiwa ItemClick dihentikan langganannya jika elemen perender Xamarin.Forms dilampirkan ke perubahan.

Berasal NativeAndroidListViewAdapter dari BaseAdapter kelas dan mengekspos Items properti yang berisi daftar data yang akan ditampilkan, serta mengambil alih Countmetode , , GetViewGetItemId, dan this[int] . Untuk informasi selengkapnya tentang penimpaan metode ini, lihat Menerapkan ListAdapter. Metode mengembalikan GetView tampilan untuk setiap baris, diisi dengan data, dan diperlihatkan dalam contoh kode berikut:

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;
}

Metode GetView ini dipanggil untuk mengembalikan sel yang akan dirender, sebagai View, untuk setiap baris data dalam daftar. Ini membuat instans View untuk setiap baris data yang akan ditampilkan di layar, dengan tampilan View instans yang ditentukan dalam file tata letak. Saat sel menghilang dari layar karena menggulir, sel akan tersedia untuk digunakan kembali. Ini menghindari pemborosan memori dengan memastikan bahwa hanya View ada instans untuk data yang ditampilkan di layar, bukan semua data dalam daftar. Untuk informasi selengkapnya tentang penggunaan kembali tampilan, lihat Penggunaan kembali Tampilan Baris.

Metode ini GetView juga mengisi instans View dengan data, termasuk membaca data gambar dari nama file yang ditentukan dalam ImageFilename properti .

Tata letak setiap sel yang dibayar oleh native ListView ditentukan dalam NativeAndroidListViewCell.axml file tata letak, yang dilampirkan oleh LayoutInflater.Inflate metode . Contoh kode berikut menunjukkan definisi tata letak:

<?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>

Tata letak ini menentukan bahwa dua TextView kontrol dan ImageView kontrol digunakan untuk menampilkan konten sel. Kedua TextView kontrol berorientasi vertikal dalam LinearLayout kontrol, dengan semua kontrol terkandung dalam RelativeLayout.

Menanggapi Perubahan Properti pada Kontrol Kustom

NativeListView.Items Jika properti berubah, karena item ditambahkan ke atau dihapus dari daftar, perender kustom perlu merespons dengan menampilkan perubahan. Ini dapat dicapai dengan mengambil OnElementPropertyChanged alih metode , yang ditunjukkan dalam contoh kode berikut:

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);
  }
}

Metode ini membuat instans NativeAndroidListViewAdapter baru kelas yang menyediakan data ke kontrol asli ListView , asalkan properti yang dapat diikat NativeListView.Items telah berubah.

Membuat Perender Kustom di UWP

Contoh kode berikut menunjukkan perender kustom untuk UWP:

[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);
        }
    }
}

Kontrol asli ListView dikonfigurasi asalkan perender kustom dilampirkan ke elemen baru Xamarin.Forms . Konfigurasi ini melibatkan pengaturan bagaimana kontrol asli ListView akan merespons item yang dipilih, mengisi data yang ditampilkan oleh kontrol, menentukan tampilan dan konten setiap sel, dan mendaftarkan penanganan aktivitas untuk memproses SelectionChanged peristiwa. Pada gilirannya, handler ini akan memanggil peristiwa yang ItemSelected disediakan oleh NativeListView kontrol kustom. Peristiwa SelectionChanged dihentikan langganannya jika elemen perender Xamarin.Forms dilampirkan ke perubahan.

Tampilan dan konten setiap sel asli ListView didefinisikan oleh bernama DataTemplateListViewItemTemplate. Ini DataTemplate disimpan dalam kamus sumber daya tingkat aplikasi, dan diperlihatkan dalam contoh kode berikut:

<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>

DataTemplate menentukan kontrol yang digunakan untuk menampilkan konten sel, serta tata letak dan tampilannya. Dua TextBlock kontrol dan Image kontrol digunakan untuk menampilkan konten sel melalui pengikatan data. Selain itu, instans digunakan ConcatImageExtensionConverter untuk menggabungkan .jpg ekstensi file ke setiap nama file gambar. Ini memastikan bahwa Image kontrol dapat memuat dan merender gambar saat Source properti diatur.

Menanggapi Perubahan Properti pada Kontrol Kustom

NativeListView.Items Jika properti berubah, karena item ditambahkan ke atau dihapus dari daftar, perender kustom perlu merespons dengan menampilkan perubahan. Ini dapat dicapai dengan mengambil OnElementPropertyChanged alih metode , yang ditunjukkan dalam contoh kode berikut:

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;
    }
}

Metode ini mengisi kembali kontrol asli ListView dengan data yang diubah, asalkan properti yang dapat diikat NativeListView.Items telah berubah.

Ringkasan

Artikel ini telah menunjukkan cara membuat perender kustom yang merangkum kontrol daftar khusus platform dan tata letak sel asli, memungkinkan kontrol lebih besar atas performa kontrol daftar asli.