Sdílet prostřednictvím


Přizpůsobení buňky ViewCell

Xamarin.Forms ViewCell je buňka, kterou lze přidat do ListView nebo TableView, která obsahuje zobrazení definované vývojářem. Tento článek ukazuje, jak vytvořit vlastní renderer pro ViewCell hostovaný uvnitř Xamarin.Forms ListView ovládacího prvku. Tím se při Xamarin.Forms posouvání ListView opakovaně nevolají výpočty rozložení.

Každá Xamarin.Forms buňka má doprovodný renderer pro každou platformu, která vytvoří instanci nativního ovládacího prvku. ViewCell Při vykreslení Xamarin.Forms aplikací se v iOSu ViewCellRenderer vytvoří instance třídy, která následně vytvoří instanci nativního UITableViewCell ovládacího prvku. Na platformě Android třída ViewCellRenderer vytvoří instanci nativního View ovládacího prvku. V Univerzální platforma Windows (UPW) třída ViewCellRenderer vytvoří instanci nativní DataTemplate. 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 ViewCell a odpovídajícími nativními ovládacími prvky, které ho implementují:

Vztah mezi ovládacím prvku ViewCell a implementací nativních ovládacích prvků

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 ViewCell . Postup je následující:

  1. Vytvořte vlastní buňku Xamarin.Forms .
  2. Spotřebujte vlastní buňku z Xamarin.Formsbuňky .
  3. Vytvořte vlastní renderer pro buňku na každé platformě.

Jednotlivé položky se teď probírají a implementují NativeCell renderer, který využívá rozložení specifické pro platformu pro každou buňku Xamarin.FormsListView hostovanou uvnitř ovládacího prvku. Tím se zastaví Xamarin.Forms opakované vyvolání výpočtů rozložení během ListView posouvání.

Vytvoření vlastní buňky

Vlastní ovládací prvek buňky lze vytvořit podtřídou ViewCell třídy, jak je znázorněno v následujícím příkladu kódu:

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

Třída NativeCell se vytvoří v projektu knihovny .NET Standard a definuje rozhraní API pro vlastní buňku. Vlastní buňka zveřejňuje NameCategoryvlastnosti a ImageFilename vlastnosti, které lze zobrazit prostřednictvím datové vazby. Další informace o datové vazbě najdete v tématu Základy datových vazeb.

Využívání vlastní buňky

Na NativeCell vlastní buňku lze odkazovat v kódu 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ů ve vlastním prvku buňky. Následující příklad kódu ukazuje, jak NativeCell lze vlastní buňku využívat stránkou 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>

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í buňku.

Následující příklad kódu ukazuje, jak NativeCell lze vlastní buňku využívat na stránce jazyka 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;
    }
    ...
}

Ovládací Xamarin.FormsListView prvek slouží k zobrazení seznamu dat, která jsou naplněna vlastností ItemSource . Strategie RecycleElement ukládání do mezipaměti se pokouší minimalizovat ListView nároky na paměť a rychlost provádění recyklací buněk seznamu. Další informace najdete v tématu Ukládání do mezipaměti Strategie.

Každý řádek v seznamu obsahuje tři položky dat – název, kategorii a název souboru obrázku. Rozložení každého řádku v seznamu je definováno odkazem DataTemplate na ListView.ItemTemplate vlastnost bindable. Definuje DataTemplate , že každý řádek dat v seznamu bude NativeCell zobrazen jeho Name, Categorya ImageFilename vlastnosti prostřednictvím datové vazby. Další informace o ovládacím ListView prvku naleznete v tématu ListView.

Do každého projektu aplikace je teď možné přidat vlastní renderer, který přizpůsobí rozložení specifické pro danou platformu pro každou buňku.

Vytvoření vlastního rendereru na jednotlivých platformách

Proces vytvoření vlastní třídy rendereru je následující:

  1. Vytvořte podtřídu ViewCellRenderer třídy, která vykreslí vlastní buňku.
  2. Přepište metodu specifickou pro platformu, která vykreslí vlastní buňku a logiku zápisu, aby ji přizpůsobila.
  3. ExportRenderer Přidejte atribut do vlastní třídy rendereru, aby bylo možné určit, že se použije k vykreslení Xamarin.Forms vlastní buňky. Tento atribut se používá k registraci vlastního rendereru v Xamarin.Forms.

Poznámka:

Pro většinu Xamarin.Forms prvků je volitelné poskytnout vlastní renderer v každém projektu platformy. Pokud není zaregistrovaný vlastní renderer, použije se výchozí renderer základní třídy ovládacího prvku. Vlastní renderery jsou však vyžadovány v každém projektu platformy při vykreslování elementu ViewCell .

Následující diagram znázorňuje zodpovědnosti jednotlivých projektů v ukázkové aplikaci spolu s relacemi mezi nimi:

Odpovědnosti vlastního vykreslovacího projektu NativeCell

Vlastní NativeCell buňka je vykreslena třídami rendereru specifické pro platformu, které jsou odvozeny od třídy pro každou platformu ViewCellRenderer . Výsledkem je vykreslení každé NativeCell vlastní buňky s rozložením specifické pro platformu, jak je znázorněno na následujících snímcích obrazovky:

NativeCell na každé platformě

Třída ViewCellRenderer zveřejňuje metody specifické pro platformu pro vykreslení vlastní buňky. Jedná se o metodu GetCell na platformě iOS, metodu GetCellCore na platformě Android a metodu GetTemplate v UPW.

Každá vlastní třída rendereru je zdobena ExportRenderer atributem, který registruje renderer s Xamarin.Forms. Atribut má dva parametry – název Xamarin.Forms typu vykreslené buňky 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(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 GetCell je volána k sestavení každé buňky, která se má zobrazit. Každá buňka je NativeiOSCell instance, která definuje rozložení buňky a jejích dat. Operace GetCell metody závisí na ListView strategii ukládání do mezipaměti:

  • ListView Pokud je RetainElementstrategie ukládání do mezipaměti , metoda bude vyvolána pro každou buňkuGetCell. Vytvoří NativeiOSCell se instance pro každou NativeCell instanci, která se na obrazovce zpočátku zobrazí. Při procházení ListViewNativeiOSCell uživatelem se instance znovu použijí. Další informace o opětovném použití buněk iOS naleznete v tématu Opakované použití buňky.

    Poznámka:

    Tento vlastní kód rendereru provede opakované použití některých buněk i v případě, že ListView je nastavena pro zachování buněk.

    Data zobrazená každou NativeiOSCell instancí, ať už nově vytvořená nebo znovu použitá, se aktualizují o data z každé NativeCell instance metodou UpdateCell .

    Poznámka:

    Metoda OnNativeCellPropertyChanged se nikdy nevyvolá, když ListView je strategie ukládání do mezipaměti nastavena pro zachování buněk.

  • ListView Při strategii RecycleElementGetCell ukládání do mezipaměti se metoda vyvolá pro každou buňku, která se na obrazovce zpočátku zobrazí. Vytvoří NativeiOSCell se instance pro každou NativeCell instanci, která se na obrazovce zpočátku zobrazí. Data zobrazená každou NativeiOSCell instancí se aktualizují o data z NativeCell instance metodou UpdateCell . Metoda se však nevyvolá, GetCell protože uživatel prochází rozhraním ListView. NativeiOSCell Místo toho se instance znovu použijí. PropertyChanged události budou v instanci vyvolány NativeCell při změně dat a obslužná rutina OnNativeCellPropertyChanged události aktualizuje data v každé znovu použité NativeiOSCell instanci.

Následující příklad kódu ukazuje metodu OnNativeCellPropertyChanged , která se vyvolá při PropertyChanged vyvolání události:

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

Tato metoda aktualizuje data zobrazená opětovnými instancemi NativeiOSCell . Kontrola změněné vlastnosti se provede, protože metodu lze volat vícekrát.

Třída NativeiOSCell definuje rozložení pro každou buňku a je znázorněna v následujícím příkladu kódu:

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

Tato třída definuje ovládací prvky použité k vykreslení obsahu buňky a jejich rozložení. Třída implementuje INativeElementView rozhraní, které je vyžadováno ListView při použití RecycleElement strategie ukládání do mezipaměti. Toto rozhraní určuje, že třída musí implementovat Element vlastnost, která by měla vrátit vlastní data buněk pro recyklované buňky.

Konstruktor NativeiOSCell inicializuje vzhled HeadingLabel, SubheadingLabela CellImageView vlastnosti. Tyto vlastnosti se používají k zobrazení dat uložených v NativeCell instanci s metodou UpdateCell , která je volána k nastavení hodnoty každé vlastnosti. Kromě toho, když ListView používá RecycleElement strategie ukládání do mezipaměti, data zobrazená HeadingLabelpomocí , SubheadingLabela CellImageView vlastnosti mohou být aktualizovány metodou OnNativeCellPropertyChanged ve vlastním rendereru.

Rozložení buňky se provádí přepsáním LayoutSubviews , které nastavuje souřadnice HeadingLabel, SubheadingLabela CellImageView v buňce.

Vytvoření vlastního rendereru v Androidu

Následující příklad kódu ukazuje vlastní renderer pro platformu 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 GetCellCore je volána k sestavení každé buňky, která se má zobrazit. Každá buňka je NativeAndroidCell instance, která definuje rozložení buňky a jejích dat. Operace GetCellCore metody závisí na ListView strategii ukládání do mezipaměti:

  • ListView Pokud je RetainElementstrategie ukládání do mezipaměti , metoda bude vyvolána pro každou buňkuGetCellCore. Vytvoří NativeAndroidCell se pro každou NativeCell instanci, která se na obrazovce zpočátku zobrazí. Při procházení ListViewNativeAndroidCell uživatelem se instance znovu použijí. Další informace o opětovném použití buňky Androidu najdete v tématu Opětovné použití zobrazení řádků.

    Poznámka:

    Všimněte si, že tento vlastní kód rendereru provede opakované použití některých buněk i v případě, že ListView je nastavena pro zachování buněk.

    Data zobrazená každou NativeAndroidCell instancí, ať už nově vytvořená nebo znovu použitá, se aktualizují o data z každé NativeCell instance metodou UpdateCell .

    Poznámka:

    Všimněte si, že zatímco OnNativeCellPropertyChanged metoda bude vyvolána, když ListView je nastavena na zachování buněk, nebude aktualizovat NativeAndroidCell hodnoty vlastnosti.

  • ListView Při strategii RecycleElementGetCellCore ukládání do mezipaměti se metoda vyvolá pro každou buňku, která se na obrazovce zpočátku zobrazí. Vytvoří NativeAndroidCell se instance pro každou NativeCell instanci, která se na obrazovce zpočátku zobrazí. Data zobrazená každou NativeAndroidCell instancí se aktualizují o data z NativeCell instance metodou UpdateCell . Metoda se však nevyvolá, GetCellCore protože uživatel prochází rozhraním ListView. NativeAndroidCell Místo toho se instance znovu použijí. PropertyChanged události budou v instanci vyvolány NativeCell při změně dat a obslužná rutina OnNativeCellPropertyChanged události aktualizuje data v každé znovu použité NativeAndroidCell instanci.

Následující příklad kódu ukazuje metodu OnNativeCellPropertyChanged , která se vyvolá při PropertyChanged vyvolání události:

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

Tato metoda aktualizuje data zobrazená opětovnými instancemi NativeAndroidCell . Kontrola změněné vlastnosti se provede, protože metodu lze volat vícekrát.

Třída NativeAndroidCell definuje rozložení pro každou buňku a je znázorněna v následujícím příkladu kódu:

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

Tato třída definuje ovládací prvky použité k vykreslení obsahu buňky a jejich rozložení. Třída implementuje INativeElementView rozhraní, které je vyžadováno ListView při použití RecycleElement strategie ukládání do mezipaměti. Toto rozhraní určuje, že třída musí implementovat Element vlastnost, která by měla vrátit vlastní data buněk pro recyklované buňky.

Konstruktor NativeAndroidCell nafoukne NativeAndroidCell rozložení a inicializuje HeadingTextView, SubheadingTextViewa ImageView vlastnosti ovládacích prvků v nafukované rozložení. Tyto vlastnosti se používají k zobrazení dat uložených v NativeCell instanci s metodou UpdateCell , která je volána k nastavení hodnoty každé vlastnosti. Kromě toho, když ListView používá RecycleElement strategie ukládání do mezipaměti, data zobrazená HeadingTextViewpomocí , SubheadingTextViewa ImageView vlastnosti mohou být aktualizovány metodou OnNativeCellPropertyChanged ve vlastním rendereru.

Následující příklad kódu ukazuje definici rozložení pro NativeAndroidCell.axml soubor 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/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>

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.

Vytvoření vlastního rendereru v UPW

Následující příklad kódu ukazuje vlastní renderer pro UPW:

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

Volá GetTemplate se metoda pro vrácení buňky, která se má vykreslit pro každý řádek dat v seznamu. Vytvoří DataTemplate pro každou NativeCell instanci, která se zobrazí na obrazovce, s DataTemplate definováním vzhledu a obsahu buňky.

Soubor DataTemplate je uložený ve slovníku prostředků na úrovni aplikace a je zobrazený v následujícím příkladu kódu:

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

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.

Shrnutí

Tento článek ukazuje, jak vytvořit vlastní renderer pro ovládací ViewCell prvek hostovaný v ovládacím Xamarin.FormsListView prvku. Tím se zastaví Xamarin.Forms opakované vyvolání výpočtů rozložení během ListView posouvání.