Populate a CarouselView with data
The .NET Multi-platform App UI (.NET MAUI) CarouselView includes the following properties that define the data to be displayed, and its appearance:
ItemsSource
, of typeIEnumerable
, specifies the collection of items to be displayed, and has a default value ofnull
.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.
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 .NET MAUI applications. For more information, see Compiled bindings.
For information on how to change the CarouselView orientation, see Specify 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 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>
<Border Stroke="DarkGray"
StrokeShape="RoundRectangle 5"
Margin="20"
Padding="20"
HeightRequest="360"
HorizontalOptions="Center"
VerticalOptions="Center">
<StackLayout>
<Label Text="{Binding Name}"
FontAttributes="Bold"
FontSize="18"
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>
</Border>
</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();
stackLayout.Add(nameLabel);
stackLayout.Add(image);
stackLayout.Add(locationLabel);
stackLayout.Add(detailsLabel);
Border border = new Border { ... };
StackLayout rootStackLayout = new StackLayout();
rootStackLayout.Add(border);
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 screenshot shows an example of templating each item:
For more information about data templates, see 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:
For more information about data template selectors, see Create a 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:
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 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>
<Border Stroke="DarkGray"
StrokeShape="RoundRectangle 5"
Margin="20"
Padding="20"
HeightRequest="360"
HorizontalOptions="Center"
VerticalOptions="Center">
<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>
</Border>
</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();
Border border = new Border { ... };
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: carouselView));
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: carouselView));
deleteSwipeItem.SetBinding(MenuItem.CommandParameterProperty, ".");
swipeView.TopItems = new SwipeItems { favoriteSwipeItem };
swipeView.BottomItems = new SwipeItems { deleteSwipeItem };
StackLayout swipeViewStackLayout = new StackLayout { ... };
swipeView.Content = swipeViewStackLayout;
border.Content = swipeView;
stackLayout.Add(border);
return stackLayout;
});
In this example, the SwipeView content is a StackLayout that defines the appearance of each item that's surrounded by a Border 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 bottom and from the top:
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 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:
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 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 typeint
, the threshold of items not yet visible in the list at which theRemainingItemsThresholdReached
event will be fired.RemainingItemsThresholdReachedCommand
, of type ICommand, which is executed when theRemainingItemsThreshold
is reached.RemainingItemsThresholdReachedCommandParameter
, of typeobject
, which is the parameter that's passed to theRemainingItemsThresholdReachedCommand
.
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.