.NET MAUI CollectionView Item Swipe

Telerik Maui Ninja image

The Item Swipe is part of Telerik UI for .NET MAUI, the most comprehensive UI suite for .NET MAUI! To try it out, sign up for a free 30-day trial and kickstart your cross-platform app development today.

.NET MAUI CollectionView provides item swipe feature—when users swipe, they reveal a designated custom view with buttons, images, etc.

The image below shows how swiping can reveal buttons on the left and right:

.NET MAUI CollectionView Item Swipe

Properties

You can use the following RadCollectionView properties to configure the item swipe feature:

  • IsItemSwipeEnabled(bool)—Indicates whether the items of the CollectionView can be swiped. The default value is False.
  • SwipeThreshold(double)—Defines the length (in pixels) of the swipe gesture that is required to trigger the feature.
  • StartSwipeLength(double)—Defines the distance that the start swiped item will be moved to and stay there until the swipe gets closed.
  • EndSwipeLength(double)—Defines the distance that the end swiped item will be moved to and stay there until the swipe gets closed.
  • StartSwipeTemplate(DataTemplate)—Defines the content that is visualized for a swipe-left (in vertical orientations) or a swipe-up (in horizontal orientations).
  • EndSwipeTemplate(DataTemplate)—Defines the content that is visualized for a swipe-right (in vertical orientations) or a swipe-down (in horizontal orientations).

Methods

The following RadCollectionView methods are related to the cell swiping feature:

  • void EndItemSwipe(bool isAnimated)—Moves the swiped item to its default position.

Check below an example of the CollectionView with StartSwipeTemplate and EndSwipeTemplate defined. Through the StartSwipeTemplate users can update a property of the data item, and through the EndSwipeTemplate users can delete an item.

1. Add sample StartSwipeTemplate and EndSwipeTemplate DataTemplates to the page's resources:

<telerik:BoolToValueConverter x:Key="VisitedToIconConverter" 
                              TrueValue="{x:Static telerik:TelerikFont.IconThumbsUp}"
                              FalseValue="{x:Static telerik:TelerikFont.IconThumbsDown}" />
<telerik:BoolToValueConverter x:Key="InvertedVisitedToIconConverter" 
                              TrueValue="{x:Static telerik:TelerikFont.IconThumbsDown}"
                              FalseValue="{x:Static telerik:TelerikFont.IconThumbsUp}" />
<DataTemplate x:Key="StartSwipeItemTemplate">
    <Grid BackgroundColor="#00897B"
          HorizontalOptions="Fill"
          VerticalOptions="Fill">
        <Label FontFamily="{x:Static telerik:TelerikFont.Name}"
               FontSize="16"
               Text="{Binding Visited, Converter={StaticResource InvertedVisitedToIconConverter}}"
               TextColor="White"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center"
               Padding="10, 0" />
        <Grid.GestureRecognizers>
            <TapGestureRecognizer Tapped="VisitItemTapped" />
        </Grid.GestureRecognizers>
    </Grid>
</DataTemplate>
<DataTemplate x:Key="EndSwipeItemTemplate">
    <Grid BackgroundColor="#89000E"
          HorizontalOptions="Fill"
          VerticalOptions="Fill">
        <Label FontFamily="{x:Static telerik:TelerikFont.Name}"
               FontSize="16"
               Text="{x:Static telerik:TelerikFont.IconDelete}"
               TextColor="White"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center"
               Padding="10, 0" />
        <Grid.GestureRecognizers>
            <TapGestureRecognizer Tapped="DeleteItemTapped" />
        </Grid.GestureRecognizers>
    </Grid>
</DataTemplate>

2. Add the CollectionView definition with IsItemSwipeEnabled applied:

<telerik:RadCollectionView x:Name="collectionView"
                           ItemsSource="{Binding Locations}"
                           IsItemSwipeEnabled="True"
                           StartSwipeTemplate="{StaticResource StartSwipeItemTemplate}"
                           EndSwipeTemplate="{StaticResource EndSwipeItemTemplate}"
                           StartSwipeLength="50"
                           EndSwipeLength="50"
                           SwipeThreshold="25">
    <telerik:RadCollectionView.ItemTemplate>
        <DataTemplate>
            <Grid RowDefinitions="Auto, Auto"
                  RowSpacing="4"
                  Padding="16, 8">
                <HorizontalStackLayout Spacing="4">
                    <Label Text="{Binding City, StringFormat='{0},'}"
                           FontSize="16"
                           FontAttributes="Bold" />
                    <Label Text="{Binding Country}"
                           FontSize="16" />
                </HorizontalStackLayout>
                <HorizontalStackLayout Grid.Row="1"
                                       Spacing="4">
                    <Label Text="Visited:"
                           TextColor="#99000000" />
                    <Label FontFamily="{x:Static telerik:TelerikFont.Name}"
                           Text="{Binding Visited, Converter={StaticResource VisitedToIconConverter}}"
                           TextColor="#99000000"
                           FontSize="12"
                           VerticalTextAlignment="Center" />
                </HorizontalStackLayout>
            </Grid>
        </DataTemplate>
    </telerik:RadCollectionView.ItemTemplate>
    <telerik:RadCollectionView.BindingContext>
        <local:ViewModel />
    </telerik:RadCollectionView.BindingContext>
</telerik:RadCollectionView>

3. Add the events defined in the DataTemplates:

private void DeleteItemTapped(object sender, TappedEventArgs e)
{
    var item = ((View)sender).BindingContext as DataModel;
    if (item != null)
    {
        this.collectionView.EndItemSwipe(true, animationFinished: () =>
        {
            (this.collectionView.BindingContext as ViewModel).Locations.Remove(item);
        });
    }
}

private void VisitItemTapped(object sender, TappedEventArgs e)
{
    var item = ((View)sender).BindingContext as DataModel;
    if (item != null)
    {
        this.collectionView.EndItemSwipe(true);
        item.Visited = !item.Visited;
    }
}

4. Add the ViewModel class:

public class ViewModel : NotifyPropertyChangedBase
{
    public ViewModel()
    {
        this.Locations = new ObservableCollection<DataModel>
        {

            new DataModel { Country = "Austria", City = "Vienna", Visited = true },
            new DataModel { Country = "Belgium", City = "Antwerp" },
            new DataModel { Country = "Denmark", City = "Copenhagen" },
            new DataModel { Country = "France", City = "Nice" },
            new DataModel { Country = "France", City = "Paris", Visited = true },
            new DataModel { Country = "Germany", City = "Berlin", Visited = true },
            new DataModel { Country = "Germany", City = "Munich" },
            new DataModel { Country = "Germany", City = "Nuremberg", Visited = true },
            new DataModel { Country = "Italy", City = "Bari" },
            new DataModel { Country = "Italy", City = "Rome" },
            new DataModel { Country = "Netherlands", City = "Amsterdam" },
            new DataModel { Country = "Portugal", City = "Lisbon" },
            new DataModel { Country = "Spain", City = "Barcelona" },
            new DataModel { Country = "Spain", City = "Madrid" },
            new DataModel { Country = "United Kingdom", City = "London" },
            new DataModel { Country = "United Kingdom", City = "Manchester" },
            new DataModel { Country = "United States", City = "New York" },
            new DataModel { Country = "United States", City = "Los Angeles" },
            new DataModel { Country = "United States", City = "Chicago" },
            new DataModel { Country = "United States", City = "Boston" },
            new DataModel { Country = "United States", City = "San Francisco" },
            new DataModel { Country = "Canada", City = "Vancouver" },
            new DataModel { Country = "Brazil", City = "Rio de Janeiro" },
            new DataModel { Country = "Brazil", City = "Sao Paulo" },
            new DataModel { Country = "Argentina", City = "Buenos Aires" },
            new DataModel { Country = "Peru", City = "Lima", Visited = true },
            new DataModel { Country = "Colombia", City = "Bogota" },
            new DataModel { Country = "Bolivia", City = "La Paz" },
            new DataModel { Country = "Venezuela", City = "Caracas" },
            new DataModel { Country = "Chile", City = "Santiago" },
            new DataModel { Country = "China", City = "Hong Kong" },
            new DataModel { Country = "China", City = "Shanghai" },
            new DataModel { Country = "India", City = "Delhi" },
            new DataModel { Country = "Japan", City = "Tokyo", Visited = true },
            new DataModel { Country = "Japan", City = "Osaka" },
            new DataModel { Country = "Vietnam", City = "Hanoi" },
            new DataModel { Country = "Thailand", City = "Bangkok" },
            new DataModel { Country = "Thailand", City = "Phuket" },
            new DataModel { Country = "Nigeria", City = "Lagos" },
            new DataModel { Country = "Egypt", City = "Cairo" },
            new DataModel { Country = "Algeria", City = "Algiers" },
            new DataModel { Country = "Australia", City = "Sydney", Visited = true },
            new DataModel { Country = "Australia", City = "Melbourne" },
            new DataModel { Country = "New Zealand", City = "Auckland" },
            new DataModel { Country = "New Zealand", City = "Wellington" }
        };
    }

    public ObservableCollection<DataModel> Locations { get; set; }
}

5. Add the business object class:

public class DataModel : NotifyPropertyChangedBase
{
    private string country;
    private string city;
    private bool visited;

    public string Country
    {
        get => this.country;
        set => this.UpdateValue(ref this.country, value);
    }

    public string City
    {
        get => this.city;
        set => this.UpdateValue(ref this.city, value);
    }

    public bool Visited
    {
        get => this.visited;
        set => this.UpdateValue(ref this.visited, value);
    }
}

See Also

In this article