如何在 MAUI Collection View 内的整个 DataTemplate 上添加点击事件

huangapple go评论67阅读模式
英文:

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

问题

如何为MAUI CollectionView中的每个项目添加完整的模板点击处理程序?

我已经看过有关TapGestureRecognizer的文档,但对于竞技元素如何执行此操作并不清楚,例如在我的情况下,内嵌在HorizontalStackLayout中。

我想要的是,在按下每个项目时打开详细视图。

附注:我还在使用CommunityToolkit(MVVM和MAUI版本)。

有什么想法吗?

英文:

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!

答案1

得分: 0

以下是您提供的代码的翻译部分:

CollectionViewDataTemplate上有一个按钮,如果点击该按钮,当前项目将从列表中删除。

您可以参考以下代码:

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

更新

如果您想在CollectionView的项目上添加一个触摸手势,您可以参考以下代码:

<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>
            </HorizontalStackLayout>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

请注意,您的原始代码中还包含了一些注释,这些注释未被翻译。如果您需要对这些注释进行翻译,请提供额外的信息。

英文:

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

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt; 
&lt;ContentPage xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             xmlns:MauiMvvmApp=&quot;clr-namespace:MauiMvvmApp226&quot;
             x:Class=&quot;MauiMvvmApp226.MainPage&quot;&gt;

    &lt;ContentPage.BindingContext&gt;
        &lt;MauiMvvmApp:TestViewModel&gt;&lt;/MauiMvvmApp:TestViewModel&gt;
    &lt;/ContentPage.BindingContext&gt;

        &lt;VerticalStackLayout
            Spacing=&quot;25&quot;
            Padding=&quot;30,0&quot;
            VerticalOptions=&quot;Start&quot;&gt;

        &lt;CollectionView  ItemsSource=&quot;{Binding Items}&quot; x:Name=&quot;mCollectionView&quot;&gt;
            &lt;CollectionView.ItemTemplate&gt;
                &lt;DataTemplate&gt;
                    &lt;HorizontalStackLayout  &gt;
                        &lt;StackLayout Orientation=&quot;Vertical&quot;&gt;
                            &lt;Label Text=&quot;{Binding Name}&quot; FontSize=&quot;Title&quot; /&gt;
                            &lt;Label Text=&quot;{Binding Description}&quot; FontSize=&quot;Subtitle&quot;/&gt;
                        &lt;/StackLayout&gt;

                        &lt;Button Text=&quot;Remove&quot;   Command=&quot;{Binding BindingContext.DeleteItemCommand, Source={x:Reference mCollectionView}}&quot;  CommandParameter=&quot;{Binding .}&quot;  Margin=&quot;10,0,10,0&quot; WidthRequest=&quot;80&quot; HorizontalOptions=&quot;End&quot;/&gt;

                    &lt;/HorizontalStackLayout&gt;
                &lt;/DataTemplate&gt;
            &lt;/CollectionView.ItemTemplate&gt;

        &lt;/CollectionView&gt;

        &lt;/VerticalStackLayout&gt;

&lt;/ContentPage&gt;

TestViewModel.cs

public partial class TestViewModel : ObservableObject 
{

    [ObservableProperty]
    private ObservableCollection&lt;ItemModel&gt; items;
   
    public TestViewModel()
    {
        PopulateObservableCollection();

    }

    public void PopulateObservableCollection()
    {
        Items = new ObservableCollection&lt;ItemModel&gt;();
        try
        {
            Items.Add(new ItemModel { Name = &quot;test1&quot;,Description= &quot;Description 1&quot; });
            Items.Add(new ItemModel {  Name = &quot;test2&quot;, Description = &quot;Description 2&quot; });
            Items.Add(new ItemModel {  Name = &quot;test3&quot;, Description = &quot;Description 3&quot; });
        }
        catch (Exception)
        { }
    }

    [RelayCommand]
    private async Task DeleteItem(ItemModel obj)
    {
        try
        {
            if (Items != null &amp;&amp; Items.Contains(obj))
            {
                Items.Remove(obj);
            }
        }
        catch (Exception ex)
        {
            await Shell.Current.DisplayAlert(&quot;Alert&quot;, ex.ToString(), &quot;Cancel&quot;);
        }
        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:

    &lt;CollectionView  ItemsSource=&quot;{Binding Items}&quot; x:Name=&quot;mCollectionView&quot;&gt; 
        &lt;CollectionView.ItemTemplate&gt;
            &lt;DataTemplate&gt;
                &lt;HorizontalStackLayout  &gt;
                    &lt;HorizontalStackLayout.GestureRecognizers&gt;
                        &lt;TapGestureRecognizer
                              Command=&quot;{Binding BindingContext.DeleteItemCommand, Source={x:Reference mCollectionView}}&quot; CommandParameter=&quot;{Binding .}&quot;&gt;
                        &lt;/TapGestureRecognizer&gt;

                    &lt;/HorizontalStackLayout.GestureRecognizers&gt;

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

                &lt;/HorizontalStackLayout&gt;
            &lt;/DataTemplate&gt;
        &lt;/CollectionView.ItemTemplate&gt;
    &lt;/CollectionView&gt;

答案2

得分: 0

感谢@Jason在开头提供的评论,最终我选择了一个简单的方法来处理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)
{
     //处理逻辑
}

感谢大家的评论和建议。

英文:

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:

&lt;CollectionView 
    ItemsSource=&quot;{Binding Items}&quot; 
    SelectionMode=&quot;Single&quot; x:Name=&quot;ItemsCollectionView&quot;
    SelectionChangedCommand=&quot;{Binding ClickCommand}&quot; 
    SelectionChangedCommandParameter=&quot;{Binding SelectedItem, Source={x:Reference ItemsCollectionView}}&quot;

ViewModel

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

Thanks all for the comment and suggestions

huangapple
  • 本文由 发表于 2023年4月17日 01:28:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76029311.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定