Я добавил команды в StackLayout в CollectionView, но команды не вызываются. Что не так? Я использовал это обучающее видео, чтобы узнать, как связать команду в CollectionView следующим образом:
<SwipeView.RightItems>
<SwipeItems>
<SwipeItem Text = "Delete" Command = "{Binding Source = {RelativeSource AncestorType = {x:Type local:ProductPageViewModel}}, Path = "ProductTappedDeleteCommand"}", CommandParameter = "{Binding .}">
</SwipeItem>
</SwipeItems>
</SwipeView.RightItems>
На видео этот код работает правильно. Я пробовал так - SwipeItem и TapGestureRecognizer не вызывают команду. Уже 2 дня пытаюсь исправить эту ошибку, не получается.
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 = "ColorLab.Pages.UserDiagnosticPage"
xmlns:models = "clr-namespace:ColorLab.Types"
xmlns:local = "clr-namespace:ColorLab.ViewModels"
Title = "UserDiagnosticPage">
<StackLayout>
<RefreshView x:DataType = "local:UserDiagnosticViewModel"
Command = "{Binding LoadDiagnosticCommand}"
IsRefreshing = "{Binding IsBusy}">
<Grid>
<CollectionView ItemsSource = "{Binding combinedUdDatas}">
<CollectionView.EmptyView>
...
</CollectionView.EmptyView>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType = "models:CombinedUdData">
<StackLayout Padding = "2">
<SwipeView>
<SwipeView.RightItems>
<SwipeItem Text = "Delete" Command = "{Binding Source = {RelativeSource AncestorType = {x:Type local:UserDiagnosticViewModel}}, Path=UdTappedDeleteCommand}" CommandParameter = "{Binding .}" BackgroundColor = "{StaticResource DangerButton}"/>
<SwipeItem Text = "Cancel" IsDestructive = "True" BackgroundColor = "{StaticResource Primary}"/>
</SwipeView.RightItems>
<Grid Padding = "10" BackgroundColor = "AliceBlue">
<Grid.RowDefinitions>
<RowDefinition Height = "30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "215" />
<ColumnDefinition Width = "45" />
<ColumnDefinition Width = "35" />
<ColumnDefinition Width = "70" />
</Grid.ColumnDefinitions>
<Label Grid.Column = "0" Text = "{Binding UserDiagnostic.SessionDate}" FontSize = "18" VerticalTextAlignment = "Center" HorizontalTextAlignment = "Start"/>
<Label Grid.Column = "1" Text = "Цвет:" FontSize = "16" VerticalTextAlignment = "Center" HorizontalTextAlignment = "Start"/>
<BoxView Grid.Column = "2" Color = "{Binding UdMauiColor[0].OriginalColor}"/>
<Image Source = "open_object.png" Grid.Column = "3" WidthRequest = "30" HeightRequest = "30">
<Image.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired = "1" Command = "{Binding Source = {RelativeSource AncestorType = {x:Type local:UserDiagnosticViewModel}}, Path=UdDiagnosticTappedCommand}"
CommandParameter = "{Binding .}">
</TapGestureRecognizer>
</Image.GestureRecognizers>
</Image>
</Grid>
</SwipeView>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</RefreshView>
</StackLayout>
</ContentPage>
.cs файл для этой страницы:
using ColorLab.ViewModels;
namespace ColorLab.Pages;
public partial class UserDiagnosticPage : ContentPage
{
UserDiagnosticViewModel _userDiagnosticViewModel;
public UserDiagnosticPage()
{
InitializeComponent();
_userDiagnosticViewModel = new(Navigation);
this.BindingContext = _userDiagnosticViewModel;
}
protected override void OnAppearing()
{
base.OnAppearing();
_userDiagnosticViewModel.OnAppering();
}
}
В UserDiagnosticViewModel я пробовал разные способы привязки команд:
using System.Collections.ObjectModel;
using System.Windows.Input;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
using ColorLab.Types;
using ColorLab.Pages;
namespace ColorLab.ViewModels
{
public partial class UserDiagnosticViewModel : BaseUdViewModel
{
public ObservableCollection<Types.CombinedUdData> combinedUdDatas { get; }
public ICommand UdTappedDeleteCommand { get; }
public UserDiagnosticViewModel(INavigation navigation)
{
combinedUdDatas = new();
Navigation = navigation;
UdTappedDeleteCommand = new RelayCommand<Types.CombinedUdData>(UdTappedDelete);
}
public void OnAppering()
{
IsBusy = true;
}
[ICommand]
private async Task LoadDiagnostic()
{
IsBusy = true;
try
{
//...
}
catch (Exception)
{
throw;
}
finally
{
IsBusy = false;
}
}
private async void UdTappedDelete(Types.CombinedUdData data)
{
if (data == null)
return;
await App.DiagnosticHistoryService.RemoveUserDiagnosticAsync(data.UserDiagnostic.Id);
await LoadDiagnostic();
OnAppering();
}
private async void UdDiagnosticTapped(Types.CombinedUdData data)
{
if (data == null)
return;
await Navigation.PushAsync(new ViewDiagnosticPage(data));
}
}
}





Ваши команды настроены неправильно.
[ICommand] генератора исходников, вы наверное имеете в виду [RelayCommand]UdDiagnosticTappedCommandasync void. Единственным исключением являются обработчики событий, которые не могут быть типа Task.Примечание. Убедитесь, что вы используете правильный инструментарий сообщества. Вы должны использовать CommunityToolkit.Mvvm для [RelayCommand], а не Microsoft Toolkit, который устарел.
Измените свою ViewModel следующим образом:
namespace ColorLab.ViewModels
{
public partial class UserDiagnosticViewModel : BaseUdViewModel
{
public ObservableCollection<Types.CombinedUdData> combinedUdDatas { get; }
public UserDiagnosticViewModel(INavigation navigation)
{
combinedUdDatas = new();
Navigation = navigation;
}
public void OnAppering()
{
IsBusy = true;
}
[RelayCommand]
private async Task LoadDiagnostic()
{
IsBusy = true;
try
{
//...
}
catch (Exception)
{
throw;
}
finally
{
IsBusy = false;
}
}
[RelayCommand]
private async Task UdTappedDelete(Types.CombinedUdData data)
{
if (data == null)
return;
await App.DiagnosticHistoryService.RemoveUserDiagnosticAsync(data.UserDiagnostic.Id);
await LoadDiagnostic();
OnAppering();
}
[RelayCommand]
private async Task UdDiagnosticTapped(Types.CombinedUdData data)
{
if (data == null)
return;
await Navigation.PushAsync(new ViewDiagnosticPage(data));
}
}
}
В вашем XAML вы должны добавить атрибут x:DataType в корень страницы, чтобы включить скомпилированные привязки, это поможет вам быстрее находить проблемы с привязками, потому что проблемы с привязками будут выдавать ошибки компилятора для вас:
<?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 = "ColorLab.Pages.UserDiagnosticPage"
xmlns:models = "clr-namespace:ColorLab.Types"
xmlns:local = "clr-namespace:ColorLab.ViewModels"
x:DataType = "local:UserDiagnosticViewModel"
Title = "UserDiagnosticPage">
<!-- ... -->
</ContentPage>
И последнее, но не менее важное: вы смешиваете пользовательский интерфейс и бизнес-логику и не следуете строго шаблону MVVM. Например, OnAppearing() — это то, о чем ViewModel не должна знать, это связано только с пользовательским интерфейсом. Ваша ViewModel также не должна знать о Pages и Views. Возможно, вы захотите переосмыслить эту часть дизайна.
У вас есть два SwipeItem, но вам не хватает <SwipeItems> в вашем xaml. Ваш Swipe должен выглядеть так:
<SwipeView.RightItems>
<SwipeItems>
<SwipeItem
BackgroundColor = "{StaticResource DangerButton}"
Command = "{Binding Source = {RelativeSource AncestorType = {x:Type local:UserDiagnosticViewModel}}, Path=UdTappedDeleteCommand}"
CommandParameter = "{Binding .}"
Text = "Delete" />
<SwipeItem
BackgroundColor = "{StaticResource Primary}"
IsDestructive = "True"
Text = "Cancel" />
</SwipeItems>
</SwipeView.RightItems>
Спасибо. Теперь я получил ошибку, потому что я сделал кривую таблицу sqlite. хД
Я смущен. Это было причиной того, что вы не могли добраться до команды. Почему это не правильный ответ? Ваши команды и все остальное в виртуальной машине работали нормально, если немного любить и заботиться.
Извини за это. Просто это не единственная проблема.
Спасибо, но это не работает для SwipeItem. Я думаю, что это проблема с интерфейсом.