Laden...

DataBinding für SwipeItem Delete in anderem Scope

Erstellt von OXO vor einem Jahr Letzter Beitrag vor einem Jahr 597 Views
O
OXO Themenstarter:in
86 Beiträge seit 2020
vor einem Jahr
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);
            }
        }
    }
}

O
OXO Themenstarter:in
86 Beiträge seit 2020
vor einem Jahr

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?