Personalizzazione dell'aspetto della cella ListView

La Xamarin.FormsListView classe viene usata per presentare elenchi scorrevoli, che possono essere personalizzati tramite l'uso di ViewCell elementi. Un ViewCell elemento può visualizzare testo e immagini, indicare uno stato true/false e ricevere l'input dell'utente.

Celle predefinite

Xamarin.Forms viene fornito con celle predefinite che funzionano per molte applicazioni:

  • TextCell i controlli vengono utilizzati per visualizzare testo con una seconda riga facoltativa per il testo dettagliato.
  • ImageCell i controlli sono simili a TextCells, ma includono un'immagine a sinistra del testo.
  • SwitchCell i controlli vengono usati per presentare e acquisire stati on/off o true/false.
  • EntryCell i controlli vengono usati per presentare dati di testo che l'utente può modificare.

I SwitchCell controlli e EntryCell vengono usati più comunemente nel contesto di un oggetto TableView.

TextCell

TextCell è una cella per la visualizzazione del testo, facoltativamente con una seconda riga come testo di dettaglio. Lo screenshot seguente mostra TextCell gli elementi in iOS e Android:

Esempio di TextCell predefinito

Il rendering di TextCells viene eseguito come controlli nativi in fase di esecuzione, quindi le prestazioni sono molto buone rispetto a un oggetto personalizzato ViewCell. TextCells è personalizzabile, consentendo di impostare le proprietà seguenti:

  • Text : il testo visualizzato sulla prima riga, in caratteri di grandi dimensioni.
  • Detail : il testo visualizzato sotto la prima riga, in un carattere più piccolo.
  • TextColor : colore del testo.
  • DetailColor – il colore del testo dei dettagli

Lo screenshot seguente mostra TextCell gli elementi con proprietà di colore personalizzate:

Esempio di TextCell personalizzato

ImageCell

ImageCell, come TextCell, può essere usato per la visualizzazione di testo e testo di dettaglio secondario e offre prestazioni elevate usando i controlli nativi di ogni piattaforma. ImageCell differisce da in TextCell quanto visualizza un'immagine a sinistra del testo.

Lo screenshot seguente mostra ImageCell gli elementi in iOS e Android:

ImageCell è utile quando è necessario visualizzare un elenco di dati con un aspetto visivo, ad esempio un elenco di contatti o film. ImageCells sono personalizzabili, consentendo di impostare:

  • Text – testo visualizzato sulla prima riga, in carattere grande
  • Detail – il testo visualizzato sotto la prima riga, in un carattere più piccolo
  • TextColor – il colore del testo
  • DetailColor – il colore del testo dei dettagli
  • ImageSource : immagine da visualizzare accanto al testo

Lo screenshot seguente mostra ImageCell gli elementi con proprietà di colore personalizzate:

Celle personalizzate

Le celle personalizzate consentono di creare layout di cella non supportati dalle celle predefinite. Ad esempio, è possibile presentare una cella con due etichette che hanno un peso uguale. Un TextCell valore sarebbe insufficiente perché ha un'etichetta TextCell più piccola. La maggior parte delle personalizzazioni delle celle aggiunge altri dati di sola lettura,ad esempio etichette aggiuntive, immagini o altre informazioni di visualizzazione.

Tutte le celle personalizzate devono derivare da , la stessa classe di base usata da ViewCelltutti i tipi di cella predefiniti.

Xamarin.Formsoffre un comportamento di memorizzazione nella cache sul ListView controllo che può migliorare le prestazioni di scorrimento per alcuni tipi di celle personalizzate.

Lo screenshot seguente mostra un esempio di cella personalizzata:

XAML

La cella personalizzata mostrata nello screenshot precedente può essere creata con il codice XAML seguente:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="demoListView.ImageCellPage">
    <ContentPage.Content>
        <ListView  x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout BackgroundColor="#eee"
                        Orientation="Vertical">
                            <StackLayout Orientation="Horizontal">
                                <Image Source="{Binding image}" />
                                <Label Text="{Binding title}"
                                TextColor="#f35e20" />
                                <Label Text="{Binding subtitle}"
                                HorizontalOptions="EndAndExpand"
                                TextColor="#503026" />
                            </StackLayout>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage.Content>
</ContentPage>

Il codice XAML funziona come segue:

  • La cella personalizzata è annidata all'interno di un DataTemplateoggetto , che si trova all'interno ListView.ItemTemplatedi . Si tratta dello stesso processo dell'uso di qualsiasi cella predefinita.
  • ViewCell è il tipo della cella personalizzata. L'elemento figlio dell'elemento DataTemplate deve essere di o derivare dalla ViewCell classe .
  • All'interno di , il ViewCelllayout può essere gestito da qualsiasi Xamarin.Forms layout. In questo esempio il layout viene gestito da un StackLayoutoggetto , che consente di personalizzare il colore di sfondo.

Nota

Qualsiasi proprietà di che è associabile può essere associata all'interno di StackLayout una cella personalizzata. Tuttavia, questa funzionalità non viene visualizzata nell'esempio XAML.

Codice

È anche possibile creare una cella personalizzata nel codice. Prima di tutto, è necessario creare una classe personalizzata che deriva da ViewCell :

public class CustomCell : ViewCell
    {
        public CustomCell()
        {
            //instantiate each of our views
            var image = new Image ();
            StackLayout cellWrapper = new StackLayout ();
            StackLayout horizontalLayout = new StackLayout ();
            Label left = new Label ();
            Label right = new Label ();

            //set bindings
            left.SetBinding (Label.TextProperty, "title");
            right.SetBinding (Label.TextProperty, "subtitle");
            image.SetBinding (Image.SourceProperty, "image");

            //Set properties for desired design
            cellWrapper.BackgroundColor = Color.FromHex ("#eee");
            horizontalLayout.Orientation = StackOrientation.Horizontal;
            right.HorizontalOptions = LayoutOptions.EndAndExpand;
            left.TextColor = Color.FromHex ("#f35e20");
            right.TextColor = Color.FromHex ("503026");

            //add views to the view hierarchy
            horizontalLayout.Children.Add (image);
            horizontalLayout.Children.Add (left);
            horizontalLayout.Children.Add (right);
            cellWrapper.Children.Add (horizontalLayout);
            View = cellWrapper;
        }
    }

Nel costruttore della pagina la proprietà di ItemTemplate ListView è impostata su un DataTemplate oggetto con il CustomCell tipo specificato:

public partial class ImageCellPage : ContentPage
    {
        public ImageCellPage ()
        {
            InitializeComponent ();
            listView.ItemTemplate = new DataTemplate (typeof(CustomCell));
        }
    }

Modifiche al contesto di associazione

Quando si esegue l'associazione alle istanze di BindableProperty un tipo di cella personalizzato, i controlli dell'interfaccia utente che visualizzano i BindableProperty valori devono usare l'override OnBindingContextChanged per impostare i dati da visualizzare in ogni cella, anziché il costruttore della cella, come illustrato nell'esempio di codice seguente:

public class CustomCell : ViewCell
{
    Label nameLabel, ageLabel, locationLabel;

    public static readonly BindableProperty NameProperty =
        BindableProperty.Create ("Name", typeof(string), typeof(CustomCell), "Name");
    public static readonly BindableProperty AgeProperty =
        BindableProperty.Create ("Age", typeof(int), typeof(CustomCell), 0);
    public static readonly BindableProperty LocationProperty =
        BindableProperty.Create ("Location", typeof(string), typeof(CustomCell), "Location");

    public string Name
    {
        get { return(string)GetValue (NameProperty); }
        set { SetValue (NameProperty, value); }
    }

    public int Age
    {
        get { return(int)GetValue (AgeProperty); }
        set { SetValue (AgeProperty, value); }
    }

    public string Location
    {
        get { return(string)GetValue (LocationProperty); }
        set { SetValue (LocationProperty, value); }
    }
    ...

    protected override void OnBindingContextChanged ()
    {
        base.OnBindingContextChanged ();

        if (BindingContext != null)
        {
            nameLabel.Text = Name;
            ageLabel.Text = Age.ToString ();
            locationLabel.Text = Location;
        }
    }
}

L'override OnBindingContextChanged verrà chiamato quando viene generato l'evento BindingContextChanged , in risposta al valore della BindingContext proprietà che cambia. Pertanto, quando cambia BindingContext , i controlli dell'interfaccia utente che visualizzano i valori devono impostare i BindableProperty dati. Si noti che l'oggetto BindingContext deve essere controllato per un null valore, in quanto può essere impostato da Xamarin.Forms per Garbage Collection, che a sua volta comporterà la chiamata dell'override OnBindingContextChanged .

In alternativa, i controlli dell'interfaccia utente possono essere associati alle BindableProperty istanze per visualizzare i relativi valori, eliminando la necessità di eseguire l'override del OnBindingContextChanged metodo.

Nota

Quando si esegue l'override di OnBindingContextChanged, assicurarsi che il metodo della classe di OnBindingContextChanged base venga chiamato in modo che i delegati registrati ricevano l'evento BindingContextChanged .

In XAML il binding del tipo di cella personalizzato ai dati può essere ottenuto come illustrato nell'esempio di codice seguente:

<ListView x:Name="listView">
    <ListView.ItemTemplate>
        <DataTemplate>
            <local:CustomCell Name="{Binding Name}" Age="{Binding Age}" Location="{Binding Location}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

In questo modo vengono associate le Nameproprietà , Agee Location associabili nell'istanza CustomCell di , alle Nameproprietà , Agee Location di ogni oggetto nell'insieme sottostante.

L'associazione equivalente in C# è illustrata nell'esempio di codice seguente:

var customCell = new DataTemplate (typeof(CustomCell));
customCell.SetBinding (CustomCell.NameProperty, "Name");
customCell.SetBinding (CustomCell.AgeProperty, "Age");
customCell.SetBinding (CustomCell.LocationProperty, "Location");

var listView = new ListView
{
    ItemsSource = people,
    ItemTemplate = customCell
};

In iOS e Android, se l'oggetto ListView ricicla gli elementi e la cella personalizzata usa un renderer personalizzato, il renderer personalizzato deve implementare correttamente la notifica delle modifiche delle proprietà. Quando le celle vengono riutilizzate, i valori delle proprietà cambiano quando il contesto di associazione viene aggiornato a quello di una cella disponibile, con PropertyChanged eventi generati. Per altre informazioni, vedere Personalizzazione di un elemento ViewCell. Per altre informazioni sul riciclo delle celle, vedere Strategia di memorizzazione nella cache.