Как превратить событие в команду в Xamarin Forms MVVM
Инструменты: я использую формы Xamarin и MVVM
Я слежу за видео: https://www.youtube.com/watch?v=7mpe_1okwxk&list=PLwOF5UVsZWUiHY1CkRVjYJ6dm0iCvAlfw&index=12
NuGet: я установил NuGet> xamarin.community.toolkit
Ошибка:
System.Reflection.TargetInvocationException: 'Исключение было создано целью вызова.'
Ваше приложение перешло в состояние останова, но нет кода для отображения, потому что все потоки выполняли внешний код (обычно код системы или платформы).
Отлаживать:
Я пытаюсь преобразовать событие выбора элемента коллекции в команду. Я знаю, что проблема связана с кодом, который пытается преобразовать событие в команду. Но я не уверен, как отладить эту ошибку. Поскольку приложение перешло в состояние останова, я не могу просто добавить точки останова. Я скопировал / вставил файл Outfile внизу этой темы
Обратите внимание, что если я удалю код, преобразующий событие в команду, он будет работать нормально. Это означает, что проблема связана с:
CollectionView.Behaviors
или же
xct:ItemSelectedEventArgsConverter
Просмотр страницы
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestApp02_MVVM_Product.Views.ProductPage"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core">
<ContentPage.Resources>
<ResourceDictionary>
<xct:ItemSelectedEventArgsConverter x:Key="ItemSelectedEventArgsConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<CollectionView ItemsSource="{Binding ProductsList}"
SelectedItem="{Binding ItemSelectedEvent, Mode=TwoWay}"
...>
<!-- Turn Event Into Command-->
<CollectionView.Behaviors>
<xct:EventToCommandBehavior
EventName="ItemSelected"
Command="{Binding ItemSelectedCommand}"
EventArgsConverter="{StaticResource ItemSelectedEventArgsConverter}"/>
</CollectionView.Behaviors>
...
</CollectionView>
...
ViewModel
using System.ComponentModel;
using System.Runtime.CompilerServices;
using TestApp02_MVVM_Product.Models;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;
using System.Threading.Tasks;
namespace TestApp02_MVVM_Product.ViewModels
{
class ProductViewModel : INotifyPropertyChanged
{
public ObservableRangeCollection<ProductModel> ProductsList { get; set; }
public AsyncCommand<ProductModel> ItemSelectedCommand { get; }
public ProductViewModel()
{
ProductsList = new ObservableRangeCollection<ProductModel>();
ProductsList.Add(new ProductModel { ProductId = 1, ProductName = "Name 1", ProductDescription = "Description 1" });
ProductsList.Add(new ProductModel { ProductId = 1, ProductName = "Name 1", ProductDescription = "Description 1" });
ProductsList.Add(new ProductModel { ProductId = 1, ProductName = "Name 1", ProductDescription = "Description 1" });
ProductsList.Add(new ProductModel { ProductId = 1, ProductName = "Name 1", ProductDescription = "Description 1" });
ItemSelectedCommand = new AsyncCommand<ProductModel>(OnItemSelectedCommand);
}//end of con
public ProductModel previousItemSelected;
public ProductModel currentItemSelected;
public ProductModel ItemSelectedEvent
{
get => currentItemSelected;
set
{
currentItemSelected = value;
OnPropertyChanged();
}
}
async Task OnItemSelectedCommand(ProductModel productModel)
{
if (productModel == null)
return;
await Application.Current.MainPage.DisplayAlert("Selected works", "yayyy", "Cancel");
}
...
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
** Выход **
[Mono] DllImport searching in: '__Internal' ('(null)').
[Mono] Searching for 'java_interop_jnienv_new_object_array'.
[Mono] Probing 'java_interop_jnienv_new_object_array'.
[Mono] Found as 'java_interop_jnienv_new_object_array'.
[Mono] DllImport searching in: '__Internal' ('(null)').
[Mono] Searching for 'java_interop_jnienv_set_object_array_element'.
[Mono] Probing 'java_interop_jnienv_set_object_array_element'.
[Mono] Found as 'java_interop_jnienv_set_object_array_element'.
[Mono] DllImport searching in: '__Internal' ('(null)').
[Mono] Searching for 'java_interop_jnienv_is_assignable_from'.
[Mono] Probing 'java_interop_jnienv_is_assignable_from'.
[Mono] Found as 'java_interop_jnienv_is_assignable_from'.
[Mono] DllImport searching in: '__Internal' ('(null)').
[Mono] Searching for 'java_interop_jnienv_new_float_array'.
[Mono] Probing 'java_interop_jnienv_new_float_array'.
[Mono] Found as 'java_interop_jnienv_new_float_array'.
[Mono] DllImport searching in: '__Internal' ('(null)').
[Mono] Searching for 'java_interop_jnienv_set_float_array_region'.
[Mono] Probing 'java_interop_jnienv_set_float_array_region'.
[Mono] Found as 'java_interop_jnienv_set_float_array_region'.
[Mono] DllImport searching in: '__Internal' ('(null)').
[Mono] Searching for 'java_interop_jnienv_get_float_array_region'.
[Mono] Probing 'java_interop_jnienv_get_float_array_region'.
[Mono] Found as 'java_interop_jnienv_get_float_array_region'.
[Mono] DllImport searching in: '__Internal' ('(null)').
[Mono] Searching for 'java_interop_jnienv_call_float_method_a'.
[Mono] Probing 'java_interop_jnienv_call_float_method_a'.
[Mono] Found as 'java_interop_jnienv_call_float_method_a'.
[Mono] DllImport searching in: '__Internal' ('(null)').
[Mono] Searching for 'java_interop_jnienv_new_local_ref'.
[Mono] Probing 'java_interop_jnienv_new_local_ref'.
[Mono] Found as 'java_interop_jnienv_new_local_ref'.
[Mono] Requesting loading reference 11 (of 12) of /data/data/com.companyname.testapp02_mvvm_product/files/.__override__/Xamarin.AndroidX.Fragment.dll
[Mono] Loading reference 11 of /data/data/com.companyname.testapp02_mvvm_product/files/.__override__/Xamarin.AndroidX.Fragment.dll asmctx DEFAULT, looking for Xamarin.AndroidX.ViewPager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
[Mono] Assembly Ref addref Xamarin.AndroidX.Fragment[0x793c9b6900] -> Xamarin.AndroidX.ViewPager[0x793c9f8300]: 3
[Mono] Requesting loading reference 12 (of 15) of /data/data/com.companyname.testapp02_mvvm_product/files/.__override__/Xamarin.Google.Android.Material.dll
[Mono] Loading reference 12 of /data/data/com.companyname.testapp02_mvvm_product/files/.__override__/Xamarin.Google.Android.Material.dll asmctx DEFAULT, looking for Xamarin.AndroidX.ViewPager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
[Mono] Assembly Ref addref Xamarin.Google.Android.Material[0x793c9f8b00] -> Xamarin.AndroidX.ViewPager[0x793c9f8300]: 4
[TabLayout] MODE_SCROLLABLE + GRAVITY_FILL is not supported, GRAVITY_START will be used instead
[Mono] Requesting loading reference 4 (of 11) of /data/data/com.companyname.testapp02_mvvm_product/files/.__override__/Xamarin.CommunityToolkit.dll
[Mono] Loading reference 4 of /data/data/com.companyname.testapp02_mvvm_product/files/.__override__/Xamarin.CommunityToolkit.dll asmctx DEFAULT, looking for System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
[Mono] Assembly Ref addref Xamarin.CommunityToolkit[0x793c9f8500] -> System[0x794c9eb480]: 9
[Mono] Requesting loading reference 9 (of 11) of /data/data/com.companyname.testapp02_mvvm_product/files/.__override__/Xamarin.CommunityToolkit.dll
[Mono] Loading reference 9 of /data/data/com.companyname.testapp02_mvvm_product/files/.__override__/Xamarin.CommunityToolkit.dll asmctx DEFAULT, looking for System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
[Mono] Assembly Ref addref Xamarin.CommunityToolkit[0x793c9f8500] -> System.Core[0x793c887980]: 5
[Mono] DllImport searching in: '__Internal' ('(null)').
[Mono] Searching for 'java_interop_jnienv_throw'.
[Mono] Probing 'java_interop_jnienv_throw'.
[Mono] Found as 'java_interop_jnienv_throw'.
**System.Reflection.TargetInvocationException:** 'Exception has been thrown by the target of an invocation.'
1 ответ
Я смешивал ListView с CollectionView. CollectionView уже имеет сборку SelectionChangedCommand, поэтому нет необходимости в элементах <CollectionView.Behaviors>
Для меня работал следующий код
Вид
<CollectionView ItemsSource="{Binding ProductsList}"
SelectedItem="{Binding ItemSelectedEvent, Mode=TwoWay}"
SelectionChangedCommand="{Binding SelectionChangedCommand}">
ViewModel
public AsyncCommand<ProductModel> SelectionChangedCommand { get; }
...
SelectionChangedCommand = new AsyncCommand<ProductModel>(OnSelectionChangedCommand);
async Task OnSelectionChangedCommand(ProductModel productModel)
{
//item is not selected so do nothing
if (productModel == null)
return;
//item is selcted so do logic here
await Application.Current.MainPage.DisplayAlert("Selected works", "yayyy", "Cancel");
}