Search code examples
c#mauimaui-community-toolkit

.NET Maui swipe-to-delete functionality is not deleting


Here is the XAML code for MainPage.xaml:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="mauiApp.MainPage"
                 xmlns:viewmodel="clr-namespace:mauiApp.ViewModel"
                 x:DataType="viewmodel:MainViewModel">
    
        <Grid RowDefinitions="100, Auto, *"
              ColumnDefinitions=".75*,.25*"
              Padding="10"
              RowSpacing="10"
              ColumnSpacing="10">
            
            <Image Grid.ColumnSpan="2"
                   Source="dotnet_bot.png"
                   BackgroundColor="Transparent"/>
    
            <Entry Placeholder="Enter task"
                   Text="{Binding Text}"
                   Grid.Row="1"/>
    
            <Button Text="Add"
                    Command="{Binding AddCommand}"
                    Grid.Row="1"
                    Grid.Column="1"/>
            
            <CollectionView Grid.Row="2" 
                            Grid.ColumnSpan="2"
                            ItemsSource="{Binding Items}">
    
                <CollectionView.ItemTemplate>
                    <DataTemplate x:DataType="{x:Type x:String}">
                        <SwipeView>
                            <SwipeView.RightItems>
                                <SwipeItem Text="Delete"
                                           BackgroundColor="Red"
                                           Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:MainViewModel}},Path=DeleteCommand}"
                                           CommandParameter="{Binding .}"/> 
                            </SwipeView.RightItems>
                            <Grid Padding="0,5">
                                <Frame>
                                    <Label Text="{Binding .}"
                                           FontSize="24"/>
                                </Frame>
                            </Grid>
                        </SwipeView>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </Grid>
    </ContentPage>

Here is the C# code for MainViewModel.cs:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;

namespace mauiApp.ViewModel
{

    public partial class MainViewModel : ObservableObject
    {
        public MainViewModel()
        {
            Items = new ObservableCollection<string>();
        }

        [ObservableProperty]
        ObservableCollection<string> items;

        [ObservableProperty]
        string text;

        [RelayCommand]
        void Add()
        {
            if(string.IsNullOrWhiteSpace(Text)) 
            { 
                return; 
            }
            Items.Add(Text);
            Text = string.Empty;
        }

        [RelayCommand]
        void Delete(string s)
        {
            if (Items.Contains(s))
            {
                Items.Remove(s);
            }

        }
    }
}

Here is the C# code for MainProgram.cs:

using mauiApp.ViewModel;

namespace mauiApp;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });

        builder.Services.AddSingleton<MainPage>();
        builder.Services.AddSingleton<MainViewModel>();
        return builder.Build();
    }
}

Here is the C# code for MainPage.xaml.cs:

using mauiApp.ViewModel;

namespace mauiApp

public partial class MainPage : ContentPage
{
    public MainPage(MainViewModel vm)
    {
        InitializeComponent();
        BindingContext = vm;
    }
}

I am trying to learn MAUI, and I copied the following code from a tutorial on the 'dotnet' YouTube channel. However, the swipe-to-delete functionality in the CollectionView is not working as expected:

  • When I swipe and tap on "Delete," the item is not being removed from the collection, and the Delete method is not being hit.

Solution

  • I suspect that RelativeSource, inside a DataTemplate, is unable to traverse up the XAML tree that refers to that DataTemplate. OR it may be because the BindingContext of the DataTemplate is an individual item, not the page's BindingContext, so MainViewModel is not found.

    An alternative technique is to use an x:Name as a Source:

    <ContentPage ...
                     x:Class="mauiApp.MainPage"
                     x:Name="thisPage"
                     ...>
                     
        ...
        <SwipeItem ...
                   Command="{Binding BindingContext.DeleteCommand, Source={x:Reference thisPage}}"
                   CommandParameter="{Binding .}"/> 
        
    

    Or if you prefer this syntax:
    Command="{Binding Source={x:Reference thisPage}, Path=BindingContext.DeleteCommand}"