Поділитися через


Xamarin.Forms CarouselView Data

CarouselView includes the following properties that define the data to be displayed, and its appearance:

  • ItemsSource, of type IEnumerable, specifies the collection of items to be displayed, and has a default value of null.
  • ItemTemplate, of type DataTemplate, specifies the template to apply to each item in the collection of items to be displayed.

These properties are backed by BindableProperty objects, which means that the properties can be targets of data bindings.

Note

CarouselView defines a ItemsUpdatingScrollMode property that represents the scrolling behavior of the CarouselView when new items are added to it. For more information about this property, see Control scroll position when new items are added.

CarouselView supports incremental data virtualization as the user scrolls. For more information, see Load data incrementally.

Populate a CarouselView with data

A CarouselView is populated with data by setting its ItemsSource property to any collection that implements IEnumerable. By default, CarouselView displays items horizontally.

Important

If the CarouselView is required to refresh as items are added, removed, or changed in the underlying collection, the underlying collection should be an IEnumerable collection that sends property change notifications, such as ObservableCollection.

CarouselView can be populated with data by using data binding to bind its ItemsSource property to an IEnumerable collection. In XAML, this is achieved with the Binding markup extension:

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

The equivalent C# code is:

CarouselView carouselView = new CarouselView();
carouselView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

In this example, the ItemsSource property data binds to the Monkeys property of the connected viewmodel.

Note

Compiled bindings can be enabled to improve data binding performance in Xamarin.Forms applications. For more information, see Compiled Bindings.

For information on how to change the CarouselView orientation, see Xamarin.Forms CarouselView Layout. For information on how to define the appearance of each item in the CarouselView, see Define item appearance. For more information about data binding, see Xamarin.Forms Data Binding.

Define item appearance

The appearance of each item in the CarouselView can be defined by setting the CarouselView.ItemTemplate property to a DataTemplate:

<CarouselView ItemsSource="{Binding Monkeys}">
    <CarouselView.ItemTemplate>
        <DataTemplate>
            <StackLayout>
                <Frame HasShadow="True"
                       BorderColor="DarkGray"
                       CornerRadius="5"
                       Margin="20"
                       HeightRequest="300"
                       HorizontalOptions="Center"
                       VerticalOptions="CenterAndExpand">
                    <StackLayout>
                        <Label Text="{Binding Name}"
                               FontAttributes="Bold"
                               FontSize="Large"
                               HorizontalOptions="Center"
                               VerticalOptions="Center" />
                        <Image Source="{Binding ImageUrl}"
                               Aspect="AspectFill"
                               HeightRequest="150"
                               WidthRequest="150"
                               HorizontalOptions="Center" />
                        <Label Text="{Binding Location}"
                               HorizontalOptions="Center" />
                        <Label Text="{Binding Details}"
                               FontAttributes="Italic"
                               HorizontalOptions="Center"
                               MaxLines="5"
                               LineBreakMode="TailTruncation" />
                    </StackLayout>
                </Frame>
            </StackLayout>
        </DataTemplate>
    </CarouselView.ItemTemplate>
</CarouselView>

The equivalent C# code is:

CarouselView carouselView = new CarouselView();
carouselView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

carouselView.ItemTemplate = new DataTemplate(() =>
{
    Label nameLabel = new Label { ... };
    nameLabel.SetBinding(Label.TextProperty, "Name");

    Image image = new Image { ... };
    image.SetBinding(Image.SourceProperty, "ImageUrl");

    Label locationLabel = new Label { ... };
    locationLabel.SetBinding(Label.TextProperty, "Location");

    Label detailsLabel = new Label { ... };
    detailsLabel.SetBinding(Label.TextProperty, "Details");

    StackLayout stackLayout = new StackLayout
    {
        Children = { nameLabel, image, locationLabel, detailsLabel }
    };

    Frame frame = new Frame { ... };
    StackLayout rootStackLayout = new StackLayout
    {
        Children = { frame }
    };

    return rootStackLayout;
});

The elements specified in the DataTemplate define the appearance of each item in the CarouselView. In the example, layout within the DataTemplate is managed by a StackLayout, and the data is displayed with an Image object, and three Label objects, that all bind to properties of the Monkey class:

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

The following screenshots show the result of templating each item:

Screenshot of CarouselView where each item is templated, on iOS and Android

For more information about data templates, see Xamarin.Forms Data Templates.

Choose item appearance at runtime

The appearance of each item in the CarouselView can be chosen at runtime, based on the item value, by setting the CarouselView.ItemTemplate property to a DataTemplateSelector object:

<ContentPage ...
             xmlns:controls="clr-namespace:CarouselViewDemos.Controls"
             x:Class="CarouselViewDemos.Views.HorizontalLayoutDataTemplateSelectorPage">
    <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>

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

The equivalent C# code is:

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

The ItemTemplate property is set to a MonkeyDataTemplateSelector object. The following example shows the MonkeyDataTemplateSelector class:

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

The MonkeyDataTemplateSelector class defines AmericanMonkey and OtherMonkey DataTemplate properties that are set to different data templates. The OnSelectTemplate override returns the AmericanMonkey template when the monkey name contains "America". When the monkey name doesn't contain "America", the OnSelectTemplate override returns the OtherMonkey template, which displays its data grayed out:

Screenshot of CarouselView runtime item template selection, on iOS and Android

For more information about data template selectors, see Create a Xamarin.Forms DataTemplateSelector.

Important

When using CarouselView, never set the root element of your DataTemplate objects to a ViewCell. This will result in an exception being thrown because CarouselView has no concept of cells.

Display indicators

Indicators, that represent the number of items and current position in a CarouselView, can be displayed next to the CarouselView. This can be accomplished with the IndicatorView control:

<StackLayout>
    <CarouselView ItemsSource="{Binding Monkeys}"
                  IndicatorView="indicatorView">
        <CarouselView.ItemTemplate>
            <!-- DataTemplate that defines item appearance -->
        </CarouselView.ItemTemplate>
    </CarouselView>
    <IndicatorView x:Name="indicatorView"
                   IndicatorColor="LightGray"
                   SelectedIndicatorColor="DarkGray"
                   HorizontalOptions="Center" />
</StackLayout>

In this example, the IndicatorView is rendered beneath the CarouselView, with an indicator for each item in the CarouselView. The IndicatorView is populated with data by setting the CarouselView.IndicatorView property to the IndicatorView object. Each indicator is a light gray circle, while the indicator that represents the current item in the CarouselView is dark gray:

Screenshot of a CarouselView and IndicatorView, on iOS and Android

Important

Setting the CarouselView.IndicatorView property results in the IndicatorView.Position property binding to the CarouselView.Position property, and the IndicatorView.ItemsSource property binding to the CarouselView.ItemsSource property.

For more information about indicators, see Xamarin.Forms IndicatorView.

Context menus

CarouselView supports context menus for items of data through the SwipeView, which reveals the context menu with a swipe gesture. The SwipeView is a container control that wraps around an item of content, and provides context menu items for that item of content. Therefore, context menus are implemented for a CarouselView by creating a SwipeView that defines the content that the SwipeView wraps around, and the context menu items that are revealed by the swipe gesture. This is achieved by adding a SwipeView to the DataTemplate that defines the appearance of each item of data in the CarouselView:

<CarouselView x:Name="carouselView"
              ItemsSource="{Binding Monkeys}">
    <CarouselView.ItemTemplate>
        <DataTemplate>
            <StackLayout>
                    <Frame HasShadow="True"
                           BorderColor="DarkGray"
                           CornerRadius="5"
                           Margin="20"
                           HeightRequest="300"
                           HorizontalOptions="Center"
                           VerticalOptions="CenterAndExpand">
                        <SwipeView>
                            <SwipeView.TopItems>
                                <SwipeItems>
                                    <SwipeItem Text="Favorite"
                                               IconImageSource="favorite.png"
                                               BackgroundColor="LightGreen"
                                               Command="{Binding Source={x:Reference carouselView}, Path=BindingContext.FavoriteCommand}"
                                               CommandParameter="{Binding}" />
                                </SwipeItems>
                            </SwipeView.TopItems>
                            <SwipeView.BottomItems>
                                <SwipeItems>
                                    <SwipeItem Text="Delete"
                                               IconImageSource="delete.png"
                                               BackgroundColor="LightPink"
                                               Command="{Binding Source={x:Reference carouselView}, Path=BindingContext.DeleteCommand}"
                                               CommandParameter="{Binding}" />
                                </SwipeItems>
                            </SwipeView.BottomItems>
                            <StackLayout>
                                <!-- Define item appearance -->
                            </StackLayout>
                        </SwipeView>
                    </Frame>
            </StackLayout>
        </DataTemplate>
    </CarouselView.ItemTemplate>
</CarouselView>

The equivalent C# code is:

CarouselView carouselView = new CarouselView();
carouselView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

carouselView.ItemTemplate = new DataTemplate(() =>
{
    StackLayout stackLayout = new StackLayout();
    Frame frame = new Frame { ... };

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

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

    swipeView.TopItems = new SwipeItems { favoriteSwipeItem };
    swipeView.BottomItems = new SwipeItems { deleteSwipeItem };

    StackLayout swipeViewStackLayout = new StackLayout { ... };
    swipeView.Content = swipeViewStackLayout;
    frame.Content = swipeView;
    stackLayout.Children.Add(frame);

    return stackLayout;
});

In this example, the SwipeView content is a StackLayout that defines the appearance of each item that's surrounded by a Frame in the CarouselView. The swipe items are used to perform actions on the SwipeView content, and are revealed when the control is swiped from the top and from the bottom:

Screenshot of CarouselView bottom context menu item, on iOS and Android Screenshot of CarouselView top menu item, on iOS and Android

SwipeView supports four different swipe directions, with the swipe direction being defined by the directional SwipeItems collection the SwipeItems objects are added to. By default, a swipe item is executed when it's tapped by the user. In addition, once a swipe item has been executed the swipe items are hidden and the SwipeView content is re-displayed. However, these behaviors can be changed.

For more information about the SwipeView control, see Xamarin.Forms SwipeView.

Pull to refresh

CarouselView supports pull to refresh functionality through the RefreshView, which enables the data being displayed to be refreshed by pulling down on the items. The RefreshView is a container control that provides pull to refresh functionality to its child, provided that the child supports scrollable content. Therefore, pull to refresh is implemented for a CarouselView by setting it as the child of a RefreshView:

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

The equivalent C# code is:

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

CarouselView carouselView = new CarouselView();
carouselView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
refreshView.Content = carouselView;
// ...

When the user initiates a refresh, the ICommand defined by the Command property is executed, which should refresh the items being displayed. A refresh visualization is shown while the refresh occurs, which consists of an animated progress circle:

Screenshot of CarouselView pull-to-refresh, on iOS and Android

The value of the RefreshView.IsRefreshing property indicates the current state of the RefreshView. When a refresh is triggered by the user, this property will automatically transition to true. Once the refresh completes, you should reset the property to false.

For more information about RefreshView, see Xamarin.Forms RefreshView.

Load data incrementally

CarouselView supports incremental data virtualization as the user scrolls. This enables scenarios such as asynchronously loading a page of data from a web service, as the user scrolls. In addition, the point at which more data is loaded is configurable so that users don't see blank space, or are stopped from scrolling.

CarouselView defines the following properties to control incremental loading of data:

  • RemainingItemsThreshold, of type int, the threshold of items not yet visible in the list at which the RemainingItemsThresholdReached event will be fired.
  • RemainingItemsThresholdReachedCommand, of type ICommand, which is executed when the RemainingItemsThreshold is reached.
  • RemainingItemsThresholdReachedCommandParameter, of type object, which is the parameter that's passed to the RemainingItemsThresholdReachedCommand.

CarouselView also defines a RemainingItemsThresholdReached event that is fired when the CarouselView is scrolled far enough that RemainingItemsThreshold items have not been displayed. This event can be handled to load more items. In addition, when the RemainingItemsThresholdReached event is fired, the RemainingItemsThresholdReachedCommand is executed, enabling incremental data loading to take place in a viewmodel.

The default value of the RemainingItemsThreshold property is -1, which indicates that the RemainingItemsThresholdReached event will never be fired. When the property value is 0, the RemainingItemsThresholdReached event will be fired when the final item in the ItemsSource is displayed. For values greater than 0, the RemainingItemsThresholdReached event will be fired when the ItemsSource contains that number of items not yet scrolled to.

Note

CarouselView validates the RemainingItemsThreshold property so that its value is always greater than or equal to -1.

The following XAML example shows a CarouselView that loads data incrementally:

<CarouselView ItemsSource="{Binding Animals}"
              RemainingItemsThreshold="2"
              RemainingItemsThresholdReached="OnCarouselViewRemainingItemsThresholdReached"
              RemainingItemsThresholdReachedCommand="{Binding LoadMoreDataCommand}">
    ...
</CarouselView>

The equivalent C# code is:

CarouselView carouselView = new CarouselView
{
    RemainingItemsThreshold = 2
};
carouselView.RemainingItemsThresholdReached += OnCollectionViewRemainingItemsThresholdReached;
carouselView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");

In this code example, the RemainingItemsThresholdReached event fires when there are 2 items not yet scrolled to, and in response executes the OnCollectionViewRemainingItemsThresholdReached event handler:

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

Note

Data can also be loaded incrementally by binding the RemainingItemsThresholdReachedCommand to an ICommand implementation in the viewmodel.