Anpassen der ListView-Zellendarstellung

Beispiel herunterladen Das Beispiel herunterladen

Die Xamarin.FormsListView -Klasse wird verwendet, um scrollbare Listen darzustellen, die mithilfe von ViewCell Elementen angepasst werden können. Ein ViewCell Element kann Text und Bilder anzeigen, einen true/false-Zustand angeben und Benutzereingaben empfangen.

Integrierte Zellen

Xamarin.Forms verfügt über integrierte Zellen, die für viele Anwendungen funktionieren:

  • TextCell Steuerelemente werden verwendet, um Text mit einer optionalen zweiten Zeile für Detailtext anzuzeigen.
  • ImageCell Steuerelemente ähneln TextCells, enthalten aber ein Bild links neben dem Text.
  • SwitchCell Steuerelemente werden verwendet, um ein-/aus- oder true/false-Zustände anzuzeigen und zu erfassen.
  • EntryCell -Steuerelemente werden verwendet, um Textdaten darzustellen, die der Benutzer bearbeiten kann.

Die SwitchCell -Steuerelemente und EntryCell werden häufiger im Kontext von TableViewverwendet.

TextCell

TextCell ist eine Zelle zum Anzeigen von Text, optional mit einer zweiten Zeile als Detailtext. Der folgende Screenshot zeigt TextCell Elemente unter iOS und Android:

TextCell-Standardbeispiel

TextCells werden zur Laufzeit als native Steuerelemente gerendert, sodass die Leistung im Vergleich zu einem benutzerdefinierten ViewCellsehr gut ist. TextCells sind anpassbar, sodass Sie die folgenden Eigenschaften festlegen können:

  • Text – der Text, der in der ersten Zeile in großer Schriftart angezeigt wird.
  • Detail – der Text, der unter der ersten Zeile in einer kleineren Schriftart angezeigt wird.
  • TextColor – die Farbe des Texts.
  • DetailColor – Die Farbe des Detailtexts

Der folgende Screenshot zeigt TextCell Elemente mit benutzerdefinierten Farbeigenschaften:

Benutzerdefiniertes TextCell-Beispiel

ImageCell

ImageCell, wie TextCell, kann zum Anzeigen von Text und sekundärem Detailtext verwendet werden und bietet eine hervorragende Leistung, indem die nativen Steuerelemente jeder Plattform verwendet werden. ImageCell unterscheidet sich dadurch TextCell , dass links neben dem Text ein Bild angezeigt wird.

Der folgende Screenshot zeigt ImageCell Elemente unter iOS und Android:

ImageCell ist nützlich, wenn Sie eine Liste von Daten mit einem visuellen Aspekt anzeigen müssen, z. B. eine Liste von Kontakten oder Filmen. ImageCells sind anpassbar, sodass Sie Folgendes festlegen können:

  • Text – der Text, der in der ersten Zeile in großer Schriftart angezeigt wird
  • Detail – der Text, der unter der ersten Zeile in einer kleineren Schriftart angezeigt wird
  • TextColor – Die Farbe des Texts
  • DetailColor – Die Farbe des Detailtexts
  • ImageSource – das Bild, das neben dem Text angezeigt werden soll

Der folgende Screenshot zeigt ImageCell Elemente mit benutzerdefinierten Farbeigenschaften:

Benutzerdefinierte Zellen

Mit benutzerdefinierten Zellen können Sie Zelllayouts erstellen, die von den integrierten Zellen nicht unterstützt werden. Beispielsweise können Sie eine Zelle mit zwei Bezeichnungen mit gleicher Gewichtung präsentieren. Eine TextCell wäre nicht ausreichend, da die TextCell eine Bezeichnung hat, die kleiner ist. Die meisten Zellanpassungen fügen zusätzliche schreibgeschützte Daten hinzu (z. B. zusätzliche Bezeichnungen, Bilder oder andere Anzeigeinformationen).

Alle benutzerdefinierten Zellen müssen von abgeleitet werden ViewCell, der gleichen Basisklasse, die alle integrierten Zelltypen verwenden.

Xamarin.Forms bietet ein Zwischenspeicherungsverhalten für das ListView Steuerelement, das die Bildlaufleistung für einige Arten von benutzerdefinierten Zellen verbessern kann.

Der folgende Screenshot zeigt ein Beispiel für eine benutzerdefinierte Zelle:

Beispiel für benutzerdefinierte Zelle

XAML

Die im vorherigen Screenshot gezeigte benutzerdefinierte Zelle kann mit dem folgenden XAML-Code erstellt werden:

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

Der XAML-Code funktioniert wie folgt:

  • Die benutzerdefinierte Zelle ist in einem DataTemplategeschachtelt, das sich in ListView.ItemTemplatebefindet. Dies ist der gleiche Prozess wie die Verwendung einer integrierten Zelle.
  • ViewCell ist der Typ der benutzerdefinierten Zelle. Das untergeordnete Element des DataTemplate Elements muss von der ViewCell -Klasse sein oder daraus abgeleitet sein.
  • Innerhalb des ViewCellLayouts kann ein beliebiges Xamarin.Forms Layout verwaltet werden. In diesem Beispiel wird das Layout von einem StackLayoutverwaltet, wodurch die Hintergrundfarbe angepasst werden kann.

Hinweis

Jede Eigenschaft von StackLayout , die gebunden werden kann, kann in einer benutzerdefinierten Zelle gebunden werden. Diese Funktion wird jedoch im XAML-Beispiel nicht angezeigt.

Code

Eine benutzerdefinierte Zelle kann auch im Code erstellt werden. Zunächst muss eine benutzerdefinierte Klasse erstellt werden, die von ViewCell abgeleitet wird:

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

Im Seitenkonstruktor wird die ListView-Eigenschaft ItemTemplate mit dem CustomCell angegebenen Typ auf ein DataTemplate festgelegt:

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

Bindungskontextänderungen

Bei der Bindung an die Instanzen eines benutzerdefinierten Zelltyps BindableProperty sollten die UI-Steuerelemente, die die BindableProperty Werte anzeigen, die OnBindingContextChanged Überschreibung verwenden, um die daten festzulegen, die in jeder Zelle angezeigt werden sollen, anstatt den Zellkonstruktor festzulegen, wie im folgenden Codebeispiel veranschaulicht:

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

Die OnBindingContextChanged Überschreibung wird aufgerufen, wenn das BindingContextChanged Ereignis ausgelöst wird, als Reaktion darauf, dass sich der Wert der BindingContext Eigenschaft ändert. Daher sollten die Benutzeroberflächensteuerelemente, die BindingContext die Werte anzeigen, ihre Daten festlegen, wenn sich die BindableProperty Änderungen ändern. Beachten Sie, dass der BindingContext auf einen null Wert überprüft werden sollte, da dies von für die Garbage Collection festgelegt Xamarin.Forms werden kann, was wiederum dazu führt, dass die OnBindingContextChanged Überschreibung aufgerufen wird.

Alternativ können UI-Steuerelemente an die BindableProperty Instanzen gebunden werden, um deren Werte anzuzeigen, sodass die -Methode nicht mehr außer Kraft gesetzt OnBindingContextChanged werden muss.

Hinweis

Stellen Sie beim Überschreiben OnBindingContextChangedsicher, dass die Methode der Basisklasse OnBindingContextChanged aufgerufen wird, damit registrierte Delegaten das BindingContextChanged Ereignis empfangen.

In XAML kann die Bindung des benutzerdefinierten Zelltyps an Daten erreicht werden, wie im folgenden Codebeispiel gezeigt:

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

Dadurch werden die Namebindungsfähigen Eigenschaften , Ageund Location im CustomCell instance an die NameEigenschaften , Ageund Location jedes -Objekt in der zugrunde liegenden Auflistung gebunden.

Die entsprechende Bindung in C# wird im folgenden Codebeispiel gezeigt:

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

Wenn es ListView sich bei iOS und Android um Recyclingelemente handelt und die benutzerdefinierte Zelle einen benutzerdefinierten Renderer verwendet, muss der benutzerdefinierte Renderer die Benachrichtigung über Eigenschaftenänderungen ordnungsgemäß implementieren. Wenn Zellen wiederverwendet werden, ändern sich ihre Eigenschaftswerte, wenn der Bindungskontext auf den einer verfügbaren Zelle aktualisiert wird, wobei PropertyChanged Ereignisse ausgelöst werden. Weitere Informationen finden Sie unter Anpassen einer ViewCell. Weitere Informationen zum Zellrecycling finden Sie unter Zwischenspeicherungsstrategie.