Auffüllen einer CollectionView mit Daten

Browse sample.Durchsuchen Sie das Beispiel

Die CollectionView der Benutzeroberfläche der .NET Multi-Plattform-App UI (.NET MAUI) enthält die folgenden Eigenschaften, die die anzuzeigenden Daten und deren Darstellung definieren:

  • ItemsSource vom Typ IEnumerable gibt die Sammlung von Elementen an, die angezeigt werden sollen, und hat einen Standardwert von null.
  • ItemTemplate vom Typ DataTemplate gibt die Vorlage an, die für jedes Element in der Sammlung von Elementen gilt, die angezeigt werden soll.

Diese Eigenschaften werden durch BindableProperty-Objekte unterstützt. Das bedeutet, dass die Eigenschaften Ziele von Datenbindungen sein können.

CollectionView definiert eine ItemsUpdatingScrollMode-Eigenschaft, die das Bildlaufverhalten des CollectionView darstellt, wenn neue Elemente hinzugefügt werden. Weitere Informationen zu dieser Eigenschaft finden Sie unter Steuern der Bildlaufposition, wenn neue Elemente hinzugefügt werden.

CollectionView unterstützt die inkrementelle Datenvirtualisierung, während der bzw. die Benutzende scrollt. Weitere Informationen finden Sie unter Inkrementelle Datenladevorgänge.

Auffüllen einer CollectionView mit Daten

Ein CollectionView wird mit Daten gefüllt, indem seine ItemsSource-Eigenschaft auf eine beliebige Sammlung gesetzt wird, die IEnumerable implementiert. Standardmäßig zeigt CollectionView Elemente in einer vertikalen Liste an.

Wichtig

Wenn die CollectionView aktualisiert werden muss, wenn Elemente hinzugefügt, entfernt oder in der zugrunde liegenden Sammlung geändert werden, sollte die zugrunde liegende Sammlung eine IEnumerable-Sammlung sein, die Benachrichtigungen über Eigenschaftsänderungen sendet, z. B. ObservableCollection.

CollectionView kann mit Daten aufgefüllt werden, indem die Datenbindung verwendet wird, um die ItemsSource-Eigenschaft an eine IEnumerable-Sammlung zu binden. In XAML wird dies mit der Binding-Markuperweiterung erreicht:

<CollectionView ItemsSource="{Binding Monkeys}" />

Der entsprechende C#-Code lautet:

CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

In diesem Beispiel werden die ItemsSource-Eigenschaftsdaten an die Monkeys-Eigenschaft vom verbundenen ViewModel gebunden.

Hinweis

Kompilierte Bindungen können aktiviert werden, um die Datenbindungsleistung in .NET MAUI-Anwendungen zu verbessern. Weitere Informationen finden Sie unter Kompilierte Bindungen.

Informationen zum Ändern des CollectionView-Layouts finden Sie unter Specify CollectionView layout. Für Informationen darüber, wie man das Aussehen der einzelnen Elemente in CollectionView definiert, siehe Das Aussehen der Elemente definieren. Weitere Informationen zur Datenbindung finden Sie unter Datenbindung.

Warnung

CollectionView löst eine Ausnahme aus, wenn sein ItemsSource aus dem UI-Thread aktualisiert wird.

Definieren der Darstellung von Elementen

Das Aussehen der einzelnen Elemente in der CollectionView kann durch die Einstellung der CollectionView.ItemTemplate-Eigenschaft auf eine DataTemplate definiert werden:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2"
                       Source="{Binding ImageUrl}"
                       Aspect="AspectFill"
                       HeightRequest="60"
                       WidthRequest="60" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold" />
                <Label Grid.Row="1"
                       Grid.Column="1"
                       Text="{Binding Location}"
                       FontAttributes="Italic"
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
    ...
</CollectionView>

Der entsprechende C#-Code lautet:

CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

collectionView.ItemTemplate = new DataTemplate(() =>
{
    Grid grid = new Grid { Padding = 10 };
    grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
    grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
    grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
    grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });

    Image image = new Image { Aspect = Aspect.AspectFill, HeightRequest = 60, WidthRequest = 60 };
    image.SetBinding(Image.SourceProperty, "ImageUrl");

    Label nameLabel = new Label { FontAttributes = FontAttributes.Bold };
    nameLabel.SetBinding(Label.TextProperty, "Name");

    Label locationLabel = new Label { FontAttributes = FontAttributes.Italic, VerticalOptions = LayoutOptions.End };
    locationLabel.SetBinding(Label.TextProperty, "Location");

    Grid.SetRowSpan(image, 2);

    grid.Add(image);
    grid.Add(nameLabel, 1, 0);
    grid.Add(locationLabel, 1, 1);

    return grid;
});

Die im DataTemplate-Objekt angegebenen Elemente definieren die Darstellung jedes Elements im Vorschlagsbereich. In diesem Beispiel wird das Layout in DataTemplate von einem Grid verwaltet. Grid enthält ein Image-Objekt und zwei Label-Objekte, die alle an Eigenschaften der Monkey-Klasse gebunden sind:

public class Monkey
{
    public string Name { get; set; }
    public string Location { get; set; }
    public string Details { get; set; }
    public string ImageUrl { get; set; }
}

Die folgenden Screenshots zeigen das Ergebnis der Vorlagenerstellung für jedes Element in der Liste:

Screenshot of CollectionView where each item is templated.

Tipp

Die Platzierung eines CollectionView innerhalb eines VerticalStackLayout kann den CollectionView-Bildlauf stoppen und die Anzahl der angezeigten Elemente begrenzen. Ersetzen Sie in diesem Fall das VerticalStackLayout durch ein Grid.

Weitere Informationen zu Datenvorlagen finden Sie unter Datenvorlagen.

Auswählen der Elementdarstellung zur Laufzeit

Das Aussehen jedes Elements in CollectionView kann zur Laufzeit auf der Grundlage des Elementwerts gewählt werden, indem die CollectionView.ItemTemplate-Eigenschaft auf ein DataTemplateSelector-Objekt gesetzt wird:

<ContentPage ...
             xmlns:controls="clr-namespace:CollectionViewDemos.Controls">
    <ContentPage.Resources>
        <DataTemplate x:Key="AmericanMonkeyTemplate">
            ...
        </DataTemplate>

        <DataTemplate x:Key="OtherMonkeyTemplate">
            ...
        </DataTemplate>

        <controls:MonkeyDataTemplateSelector x:Key="MonkeySelector"
                                             AmericanMonkey="{StaticResource AmericanMonkeyTemplate}"
                                             OtherMonkey="{StaticResource OtherMonkeyTemplate}" />
    </ContentPage.Resources>

    <CollectionView ItemsSource="{Binding Monkeys}"
                    ItemTemplate="{StaticResource MonkeySelector}" />
</ContentPage>

Der entsprechende C#-Code lautet:

CollectionView collectionView = new CollectionView
{
    ItemTemplate = new MonkeyDataTemplateSelector { ... }
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

Die ItemTemplate-Eigenschaft ist auf das MonkeyDataTemplateSelector-Objekt festgelegt. Im folgenden Beispiel wird die MonkeyDataTemplateSelector-Klasse gezeigt:

public class MonkeyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate AmericanMonkey { get; set; }
    public DataTemplate OtherMonkey { get; set; }

    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {
        return ((Monkey)item).Location.Contains("America") ? AmericanMonkey : OtherMonkey;
    }
}

Die MonkeyDataTemplateSelector-Klasse definiert AmericanMonkey- und OtherMonkeyDataTemplate-Eigenschaften, die auf verschiedene Datenvorlagen festgelegt werden. Die OnSelectTemplate-Überschreibung gibt die AmericanMonkey-Vorlage zurück, die den Affennamen und die Position in Türkis anzeigt, wenn der Affenname „Amerika“ enthält. Wenn der Affenname nicht „Amerika“ enthält, gibt die OnSelectTemplate Überschreibung die OtherMonkey Vorlage zurück, die den Affennamen und die Position in Silber anzeigt:

Screenshot of CollectionView runtime item template selection.

Weitere Informationen zu Datenvorlagenselektoren finden Sie unter Datenvorlagenselektoren erstellen.

Wichtig

Wenn Sie CollectionView verwenden, setzen Sie das Stammelement Ihrer DataTemplate-Objekte niemals auf ein ViewCell. Dies führt dazu, dass eine Ausnahme ausgelöst wird, da CollectionView kein Zellkonzept hat.

Kontextmenüs

CollectionView unterstützt Kontextmenüs für Datenelemente durch die SwipeView, die das Kontextmenü mit einer Wischgeste öffnet. Die SwipeView ist ein Containersteuerelement, das ein Inhaltselement umschließt und Kontextmenüelemente für dieses Inhaltselement bereitstellt. Daher werden Kontextmenüs für ein CollectionView implementiert, indem ein SwipeView erstellt wird, das den Inhalt definiert, um den sich das SwipeView wickelt, sowie die Kontextmenüelemente, die durch die Wischgeste angezeigt werden. Dies wird erreicht, indem die SwipeView als Stammansicht in der DataTemplate festgelegt wird, die das Aussehen der einzelnen Datenelemente in der CollectionView definiert:

<CollectionView x:Name="collectionView"
                ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <SwipeView>
                <SwipeView.LeftItems>
                    <SwipeItems>
                        <SwipeItem Text="Favorite"
                                   IconImageSource="favorite.png"
                                   BackgroundColor="LightGreen"
                                   Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.FavoriteCommand}"
                                   CommandParameter="{Binding}" />
                        <SwipeItem Text="Delete"
                                   IconImageSource="delete.png"
                                   BackgroundColor="LightPink"
                                   Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.DeleteCommand}"
                                   CommandParameter="{Binding}" />
                    </SwipeItems>
                </SwipeView.LeftItems>
                <Grid BackgroundColor="White"
                      Padding="10">
                    <!-- Define item appearance -->
                </Grid>
            </SwipeView>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Der entsprechende C#-Code lautet:

CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

collectionView.ItemTemplate = new DataTemplate(() =>
{
    // Define item appearance
    Grid grid = new Grid { Padding = 10, BackgroundColor = Colors.White };
    // ...

    SwipeView swipeView = new SwipeView();
    SwipeItem favoriteSwipeItem = new SwipeItem
    {
        Text = "Favorite",
        IconImageSource = "favorite.png",
        BackgroundColor = Colors.LightGreen
    };
    favoriteSwipeItem.SetBinding(MenuItem.CommandProperty, new Binding("BindingContext.FavoriteCommand", source: collectionView));
    favoriteSwipeItem.SetBinding(MenuItem.CommandParameterProperty, ".");

    SwipeItem deleteSwipeItem = new SwipeItem
    {
        Text = "Delete",
        IconImageSource = "delete.png",
        BackgroundColor = Colors.LightPink
    };
    deleteSwipeItem.SetBinding(MenuItem.CommandProperty, new Binding("BindingContext.DeleteCommand", source: collectionView));
    deleteSwipeItem.SetBinding(MenuItem.CommandParameterProperty, ".");

    swipeView.LeftItems = new SwipeItems { favoriteSwipeItem, deleteSwipeItem };
    swipeView.Content = grid;    
    return swipeView;
});

In diesem Beispiel ist der SwipeView-Inhalt ein Grid, der das Aussehen jedes Elements im CollectionView definiert. Die Wischelemente werden verwendet, um Aktionen für den SwipeView-Inhalt auszuführen, und werden angezeigt, wenn das Steuerelement von der linken Seite aus gewischt wird:

Screenshot of CollectionView context menu items.

SwipeView unterstützt vier verschiedene Wischrichtungen, wobei die Wischrichtung durch die direktionale SwipeItems-Sammlung definiert wird, zu der die SwipeItems-Objekte hinzugefügt werden. Standardmäßig wird ein Wischelement ausgeführt, wenn es von dem bzw. der Benutzenden angetippt wird. Darüber hinaus werden die Wischelemente ausgeblendet, sobald ein Wischelement ausgeführt wurde und der SwipeView-Inhalt erneut angezeigt wird. Dieses Verhalten kann jedoch geändert werden.

Weitere Informationen zum Steuerelement SwipeView finden Sie unter SwipeView.

Aktualisierung durch Ziehen

CollectionView unterstützt die Pull-to-Refresh-Funktionalität durch die RefreshView, die es ermöglicht, die angezeigten Daten durch Ziehen nach unten auf der Liste der Elemente zu aktualisieren. Die RefreshView ist ein Containersteuerelement, das Pull-to-Refresh-Funktionalität für sein untergeordnetes Element bereitstellt, vorausgesetzt, das untergeordnete Element unterstützt bildlauffähige Inhalte. Daher wird das Pull-to-Refresh-Verfahren für ein CollectionView implementiert, indem es als untergeordnetes Element eines RefreshView festgelegt wird:

<RefreshView IsRefreshing="{Binding IsRefreshing}"
             Command="{Binding RefreshCommand}">
    <CollectionView ItemsSource="{Binding Animals}">
        ...
    </CollectionView>
</RefreshView>

Der entsprechende C#-Code lautet:

RefreshView refreshView = new RefreshView();
ICommand refreshCommand = new Command(() =>
{
    // IsRefreshing is true
    // Refresh data here
    refreshView.IsRefreshing = false;
});
refreshView.Command = refreshCommand;

CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
refreshView.Content = collectionView;
// ...

Wenn der bzw. die Benutzende eine Aktualisierung initiiert, wird der ICommand, der durch die Eigenschaft Command definiert ist, ausgeführt, wodurch die angezeigten Elemente aktualisiert werden sollten. Während der Aktualisierung wird eine Aktualisierungsvisualisierung angezeigt, die aus einem animierten Statuskreis besteht:

Screenshot of CollectionView pull-to-refresh.

Der Wert der Eigenschaft RefreshView.IsRefreshing gibt den aktuellen Status der RefreshView an. Wenn eine Aktualisierung von dem bzw. der Benutzenden ausgelöst wird, wechselt diese Eigenschaft automatisch zu true. Nach Abschluss der Aktualisierung sollten Sie die Eigenschaft auf false zurücksetzen.

Weitere Informationen zur RefreshView finden Sie unter RefreshView.

Daten inkrementell laden

CollectionView unterstützt die inkrementelle Datenvirtualisierung, während der bzw. die Benutzende scrollt. Dies ermöglicht Szenarien wie das asynchrone Laden einer Datenseite aus einem Webdienst, während der bzw. die Benutzende scrollt. Darüber hinaus ist der Punkt, an dem mehr Daten geladen werden, konfigurierbar, sodass Benutzende keinen leeren Platz sehen oder nicht mehr scrollen können.

CollectionView definiert die folgenden Eigenschaften, um das inkrementelle Laden von Daten zu steuern:

  • RemainingItemsThreshold, vom Typ int, der Schwellenwert der noch nicht sichtbaren Elemente in der Liste, bei dem das Ereignis RemainingItemsThresholdReached ausgelöst wird.
  • RemainingItemsThresholdReachedCommand vom Typ ICommand, der ausgeführt wird, wenn der RemainingItemsThreshold erreicht wird.
  • RemainingItemsThresholdReachedCommandParameter, vom Typ object: Parameter, der an den RemainingItemsThresholdReachedCommand übergeben wird.

CollectionView definiert auch ein RemainingItemsThresholdReached-Ereignis, das ausgelöst wird, wenn der CollectionView-Bildlauf weit genug ist, sodass RemainingItemsThreshold-Elemente nicht angezeigt wurden. Dieses Ereignis kann bearbeitet werden, um weitere Elemente zu laden. Wenn das Ereignis RemainingItemsThresholdReached ausgelöst wird, wird außerdem der RemainingItemsThresholdReachedCommand ausgeführt und ermöglicht inkrementelles Laden von Daten, um in einem ViewModel stattzufinden.

Der Standardwert der Eigenschaft RemainingItemsThreshold ist -1, der angibt, dass das Ereignis RemainingItemsThresholdReached nie ausgelöst wird. Wenn der Eigenschaftswert 0 ist, wird das Ereignis RemainingItemsThresholdReached ausgelöst, wenn das letzte Element in der ItemsSource angezeigt wird. Bei Werten, die größer als 0 sind, wird das Ereignis RemainingItemsThresholdReached ausgelöst, wenn die ItemsSource diejenige Anzahl der Elemente enthält, zu denen noch kein Bildlauf durchgeführt wurde.

Hinweis

CollectionView überprüft die RemainingItemsThreshold Eigenschaft so, dass der Wert immer größer oder gleich -1 ist.

Das folgende XAML-Beispiel zeigt eine CollectionView, die die Daten inkrementell lädt:

<CollectionView ItemsSource="{Binding Animals}"
                RemainingItemsThreshold="5"
                RemainingItemsThresholdReached="OnCollectionViewRemainingItemsThresholdReached">
    ...
</CollectionView>

Der entsprechende C#-Code lautet:

CollectionView collectionView = new CollectionView
{
    RemainingItemsThreshold = 5
};
collectionView.RemainingItemsThresholdReached += OnCollectionViewRemainingItemsThresholdReached;
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");

In diesem Codebeispiel wird das RemainingItemsThresholdReached-Ereignis ausgelöst, wenn noch kein Bildlauf von fünf Elementen erfolgt und als Reaktion der OnCollectionViewRemainingItemsThresholdReached-Ereignisbehandler ausgeführt wird:

void OnCollectionViewRemainingItemsThresholdReached(object sender, EventArgs e)
{
    // Retrieve more data here and add it to the CollectionView's ItemsSource collection.
}

Hinweis

Daten können auch inkrementell geladen werden, indem der RemainingItemsThresholdReachedCommand an eine ICommand Implementierung im ViewModel gebunden wird.