微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 Xamarin Forms MVVM 中将事件转换为命令

如何解决如何在 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: '调用的目标已抛出异常。'

您的应用已进入中断状态,但没有代码显示,因为所有线程都在执行外部代码(通常是系统或框架代码)。

调试:

我正在尝试将 Collection ItemSelect 事件转换为命令。我知道问题在于试图将事件转换为命令的代码,但我不确定如何调试此错误。由于应用程序已进入中断状态,我不能简单地添加断点。我在本主题底部复制/粘贴了输出文件

请注意,如果我删除了将事件转换为命令的代码,它可以正常工作。所以这意味着问题在于:CollectionView.Behaviorsxct: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,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,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,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,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.'

解决方法

我把 ListView 和 CollectionView 混在一起了。 CollectionView 已经有内置的 SelectionChangedCommand 所以不需要 东西

以下代码对我有用

查看

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。