xaberue
xaberue

Reputation: 336

How to add on Click event on entire DataTemplate inside MAUI Collection View

How can I add a full template click handler for each item in a MAUI CollectionView?

I have seen the documentation about TapGestureRecognizer but it is not clear to me how to do it for a competitive element, for example in my case inside a HorizontalStackLayout

 <CollectionView ItemsSource="{Binding Items}">
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType="{x:Type dtos:ItemDto}">
            <HorizontalStackLayout>
                <Image WidthRequest="75" HeightRequest="75" Source="item_default.png"></Image>
                <StackLayout Orientation="Vertical">
                    <Label Text="{Binding Name}" FontSize="Title" />
                    <Label Text="{Binding Description}" FontSize="Subtitle"/>
                </StackLayout>
            </HorizontalStackLayout>                
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

What I want is to open a detail view of each item in case of pressing on it.

Side note: I'm also using CommunityToolkit (MVVM and MAUI ones)

Any ideas? Many thanks!

Upvotes: 1

Views: 4707

Answers (2)

xaberue
xaberue

Reputation: 336

Thanks to the comment provided at the beginning from @Jason, at the end I opted for a simple approach with the events of the CollectionView:

XAML:

<CollectionView 
    ItemsSource="{Binding Items}" 
    SelectionMode="Single" x:Name="ItemsCollectionView"
    SelectionChangedCommand="{Binding ClickCommand}" 
    SelectionChangedCommandParameter="{Binding SelectedItem, Source={x:Reference ItemsCollectionView}}"

ViewModel

[RelayCommand]
private async Task ClickAsync(PlaceDto place)
{
     //Handle logic
}

Thanks all for the comment and suggestions

Upvotes: 2

Jessie Zhang -MSFT
Jessie Zhang -MSFT

Reputation: 13879

Suppose there is a button on the DataTemplate of CollectionView, and if we click the button ,the current item will be removed from the list.

You can refer to the following code:

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"
             xmlns:MauiMvvmApp="clr-namespace:MauiMvvmApp226"
             x:Class="MauiMvvmApp226.MainPage">

    <ContentPage.BindingContext>
        <MauiMvvmApp:TestViewModel></MauiMvvmApp:TestViewModel>
    </ContentPage.BindingContext>

        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Start">

        <CollectionView  ItemsSource="{Binding Items}" x:Name="mCollectionView">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <HorizontalStackLayout  >
                        <StackLayout Orientation="Vertical">
                            <Label Text="{Binding Name}" FontSize="Title" />
                            <Label Text="{Binding Description}" FontSize="Subtitle"/>
                        </StackLayout>

                        <Button Text="Remove"   Command="{Binding BindingContext.DeleteItemCommand, Source={x:Reference mCollectionView}}"  CommandParameter="{Binding .}"  Margin="10,0,10,0" WidthRequest="80" HorizontalOptions="End"/>

                    </HorizontalStackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>

        </CollectionView>

        </VerticalStackLayout>

</ContentPage>

TestViewModel.cs

public partial class TestViewModel : ObservableObject 
{

    [ObservableProperty]
    private ObservableCollection<ItemModel> items;
   
    public TestViewModel()
    {
        PopulateObservableCollection();

    }

    public void PopulateObservableCollection()
    {
        Items = new ObservableCollection<ItemModel>();
        try
        {
            Items.Add(new ItemModel { Name = "test1",Description= "Description 1" });
            Items.Add(new ItemModel {  Name = "test2", Description = "Description 2" });
            Items.Add(new ItemModel {  Name = "test3", Description = "Description 3" });
        }
        catch (Exception)
        { }
    }

    [RelayCommand]
    private async Task DeleteItem(ItemModel obj)
    {
        try
        {
            if (Items != null && Items.Contains(obj))
            {
                Items.Remove(obj);
            }
        }
        catch (Exception ex)
        {
            await Shell.Current.DisplayAlert("Alert", ex.ToString(), "Cancel");
        }
        finally
        {
        }
    }
}

ItemModel.cs

public class ItemModel 
{
    public string Name { get; set; }
    public string Description { get; set; }
}

Update

If you want to add a tap gesture on the item of the collectionview, you can refer to the following code:

    <CollectionView  ItemsSource="{Binding Items}" x:Name="mCollectionView"> 
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <HorizontalStackLayout  >
                    <HorizontalStackLayout.GestureRecognizers>
                        <TapGestureRecognizer
                              Command="{Binding BindingContext.DeleteItemCommand, Source={x:Reference mCollectionView}}" CommandParameter="{Binding .}">
                        </TapGestureRecognizer>

                    </HorizontalStackLayout.GestureRecognizers>

                    <StackLayout Orientation="Vertical">
                        <Label Text="{Binding Name}" FontSize="Title" />
                        <Label Text="{Binding Description}" FontSize="Subtitle"/>
                    </StackLayout>
                    
                    <!-- <Button Text="Remove"   Command="{Binding BindingContext.DeleteItemCommand, Source={x:Reference mCollectionView}}"  CommandParameter="{Binding .}"  Margin="10,0,10,0" WidthRequest="80" HorizontalOptions="End"/>-->

                </HorizontalStackLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>

Upvotes: 0

Related Questions