Laden...

DataBinding für SwipeItem Delete in anderem Scope

Letzter Beitrag vor einem Jahr 2 Posts 799 Views
DataBinding für SwipeItem Delete in anderem Scope

Hallo,

ich habe in einer ContentPage ein wenig mit DataBinding in einem SwipeItem experimentiert und wollte dort ein Delete-Command einrichten, was aber nicht in der Person-Klasse selbst liegt und über das DataTemplate referenziert wird, sondern in es liegt in meiner ViewModel-Klasse "Tab2ViewViewModel".

Über folgenden Code komme ich irgendwie nicht an mein "DeleteItem" ran und weiß auch nicht, wie das ich dem Command-Handler meine aktuell zu löschende Person als Parameter mitgeben kann. Die Person-Klasse liegt unter dem Namespace "MyApp.Models" und die Command-Handler sind in der Klasse "Tab2ViewViewModel", welche im Namespace MyApp.ViewModels liegt.


<?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:viewmodel="clr-namespace:MyApp.ViewModels"
             xmlns:models="clr-namespace:MyApp.Models"
             x:DataType="viewmodel:Tab2ViewViewModel"
             x:Class="MyApp.Pages.Tab2View"
             Title="Tab 2 View">

    <ContentPage.ToolbarItems>
        <ToolbarItem IconImageSource="..." Command="{Binding AddNewItemCommand}" />
    </ContentPage.ToolbarItems>

    <Grid RowDefinitions="20, Auto" RowSpacing="10"  Margin="20, 0, 20, 20">
        <SearchBar Grid.Row="0" Grid.Column="0" Grid.RowSpan="5" Placeholder="Tab 2 Item search..." />

        <CollectionView Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Margin="0, 20, 0, 0"
                        ItemsSource="{Binding Items}">

            <CollectionView.ItemTemplate>
                <DataTemplate x:DataType="{x:Type models:Person}">
                    <SwipeView>
                        <SwipeView.RightItems>
                            <SwipeItems>
                                 <SwipeItem Text="Delete" BackgroundColor="Red" 
                                           Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:Tab2ViewViewModel}}, Path=DeleteItem}"
                                           CommandParameter="{Binding .}"/>
                            </SwipeItems>
                        </SwipeView.RightItems>
                        <Grid Padding="0, 5">
                            <Frame>
                                <Label Text="{Binding Name}" FontAttributes="Bold" />
                            </Frame>
                        </Grid>
                    </SwipeView>
                </DataTemplate>
            </CollectionView.ItemTemplate>

        </CollectionView>

    </Grid>

</ContentPage>


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

namespace MyApp.ViewModels
{
    public partial class Tab2ViewViewModel : ObservableObject
    {
        private static int _personCounter = 1;

        [ObservableProperty]
        private ObservableCollection<Person> items;

        [ObservableProperty] 
        private Person personItem;


        public Tab2ViewViewModel()
        {
            items = new ObservableCollection<Person>();
        }


        [RelayCommand]
        private void AddNewItemCommand()
        {
            personItem = new Person();
            personItem.Name = $"Person {_personCounter++}";

            items.Add(personItem);
        }

        [RelayCommand]
        private void DeleteItem(Person item)
        {
            if (items.Contains(item))
            {
                items.Remove(item);
            }
        }
    }
}

Jetzt habe ich den Fehler gefunden - ist mir fast nicht aufgefallen:

Das MVVM-Toolkit erzeugt ja Code für die als

[RelayCommand]

attributierten Command-Handling-Methoden und baut da als Suffix noch ein "..Command" mit dazu.
Heißt also, mein Command-Handler heißt hier nicht "DeleteItem", sondern "DeleteItemCommand".

Mein Code bei den SwipeItems müsste also wie folgt aussehen:


...
<SwipeItems>
    <SwipeItem Text="Delete" BackgroundColor="Red"
                       Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:Tab2ViewViewModel}}, Path=DeleteItemCommand}"
                       CommandParameter="{Binding .}"/>
</SwipeItems>
...

So kommt er dann über die RelativeSource und den AncestorType mit dem entsprechenden Path auch auf den Command-Handler drauf.

PS: Was mich nur sehr verwirrt hat, ich sehe bei Project > Dependencies > net7.0-android > Analyzers > CommunityToolkit.Mvvm.SourceGenerators > CommunityToolkit.Mvvm.SourceGenerators.RelayCommandGenerator bzw. den anderen Unterkategorien von CommunityToolkit.Mvvm.SourceGenerators nicht immer die Implementierungen, sondern ein schwarzes Symbol und nix weiter. Woran kann das denn liegen?