Anpassen der Darstellung von ListView-Zellen

Die Xamarin.FormsListView Klasse wird verwendet, um bildlauffähige 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.

Integriert in Zellen

Xamarin.Forms enthält integrierte Zellen, die für viele Anwendungen funktionieren:

  • TextCell Steuerelemente werden zum Anzeigen von Text mit einer optionalen zweiten Zeile für Detailtext verwendet.
  • ImageCell Steuerelemente ähneln TextCells, fügen aber links neben dem Text ein Bild ein.
  • SwitchCell Steuerelemente werden zum Anzeigen und Erfassen von Ein-/Aus- oder True/False-Zuständen verwendet.
  • EntryCell Steuerelemente werden verwendet, um Textdaten darzustellen, die der Benutzer bearbeiten kann.

Die SwitchCell Steuerelemente EntryCell werden häufiger im Kontext einer TableView.

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:

StandardtextCell(Beispiel)

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

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

Der folgende Screenshot zeigt TextCell Elemente mit angepassten Farbeigenschaften:

Beispiel für benutzerdefinierte TextCell

ImageCell

ImageCell, wie TextCell, kann zum Anzeigen von Text und sekundärem Detailtext verwendet werden und bietet eine hervorragende Leistung, indem die systemeigenen Steuerelemente der einzelnen Plattform verwendet werden. ImageCell unterscheidet sich davon TextCell , dass ein Bild links vom Text 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 angezeigt wird, in großer Schriftart
  • Detail – der Text, der unter der ersten Zeile angezeigt wird, in einer kleineren Schriftart
  • 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 angepassten Farbeigenschaften:

Benutzerdefinierte Zellen

Mit benutzerdefinierten Zellen können Sie Zellenlayouts erstellen, die von den integrierten Zellen nicht unterstützt werden. Sie können z. B. eine Zelle mit zwei Beschriftungen mit gleicher Gewichtung präsentieren. A TextCell wäre nicht ausreichend, da die TextCell Bezeichnung eine kleinere Bezeichnung aufweist. 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 ViewCellder gleichen Basisklasse abgeleitet werden, von der alle integrierten Zelltypen verwendet werden.

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:

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 einer DataTemplategeschachtelten Zelle geschachtelt, die sich innerhalb ListView.ItemTemplatebefindet. Dies ist derselbe Prozess wie die Verwendung einer integrierten Zelle.
  • ViewCell ist der Typ der benutzerdefinierten Zelle. Das untergeordnete Element des DataTemplate Elements muss von der Klasse oder von dieser ViewCell abgeleitet sein.
  • Innerhalb des ViewCellLayouts kann ein beliebiges Xamarin.Forms Layout verwaltet werden. In diesem Beispiel wird das Layout durch ein StackLayoutLayout verwaltet, mit dem die Hintergrundfarbe angepasst werden kann.

Hinweis

Jede Eigenschaft, die StackLayout gebunden werden kann, kann innerhalb 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, von ViewCell der 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 auf einen DataTemplate mit dem CustomCell angegebenen Typ festgelegt:

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

Bindungskontextänderungen

Beim Binden 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 dem Zellenkonstruktor, wie im folgenden Codebeispiel gezeigt:

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 Außerkraftsetzung wird aufgerufen, wenn das BindingContextChanged Ereignis ausgelöst wird, als Reaktion auf den Wert der Geänderten BindingContext Eigenschaft. Daher sollten die Ui-Steuerelemente, die die Werte anzeigen, ihre BindableProperty Daten festlegen, wenn sich die BindingContext Änderungen ändern. Beachten Sie, dass die BindingContext Überprüfung auf einen null Wert erfolgen soll, da dies für Xamarin.Forms die Garbage Collection festgelegt werden kann, was wiederum dazu führt, dass die OnBindingContextChanged Außerkraftsetzung aufgerufen wird.

Alternativ können UI-Steuerelemente an die BindableProperty Instanzen gebunden werden, um ihre Werte anzuzeigen, wodurch die Notwendigkeit zum Überschreiben der OnBindingContextChanged Methode entfernt wird.

Hinweis

Stellen Sie beim Überschreiben OnBindingContextChangedsicher, dass die Methode der Basisklasse OnBindingContextChanged aufgerufen wird, damit registrierte Stellvertretungen 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 NameEigenschaften , Ageund Location bindungsfähige Eigenschaften in der CustomCell Instanz, an das Name, Ageund Location die Eigenschaften jedes Objekts 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
};

Bei iOS und Android muss der benutzerdefinierte Renderer die Eigenschaftsänderungsbenachrichtigung ordnungsgemäß implementieren, wenn die ListView elemente wiederverwenden und die benutzerdefinierte Zelle einen benutzerdefinierten Renderer verwendet. Wenn Zellen wiederverwendet werden, ändern sich ihre Eigenschaftswerte, wenn der Bindungskontext auf die 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 Caching Strategy.