gpt4 book ai didi

c# - 从 View 模型导航到mvvmcross中的另一个 View 模型时崩溃

转载 作者:行者123 更新时间:2023-12-03 11:02:50 25 4
gpt4 key购买 nike

我想使用mvvmcross中的viewmodels从一个屏幕移动到下一个屏幕,并将一些模型传递给下一个ViewModel。但是我正在崩溃以下:

MvvmCross.Platform.Exceptions.MvxException: Failed to construct and initialize ViewModel for type iManage.ViewModels.LoginViewModel from locator MvxDefaultViewModelLocator - check InnerException for more information ---> MvvmCross.Platform.Exceptions.MvxException: Problem creating viewModel of type LoginViewModel ---> MvvmCross.Platform.Exceptions.MvxIoCResolveException: Failed to resolve parameter for parameter item of type SchoolModel when creating iManage.ViewModels.LoginViewModel at MvvmCross.Platform.IoC.MvxSimpleIoCContainer.GetIoCParameterValues (System.Type type, System.Reflection.ConstructorInfo firstConstructor) [0x00066] in <6adc0d5857264558a9d45778a78ae02a>:0 at MvvmCross.Platform.IoC.MvxSimpleIoCContainer.IoCConstruct (System.Type type) [0x0002c] in <6adc0d5857264558a9d45778a78ae02a>:0 at MvvmCross.Platform.Mvx.IocConstruct (System.Type t) [0x00006] in <6adc0d5857264558a9d45778a78ae02a>:0 at MvvmCross.Core.ViewModels.MvxDefaultViewModelLocator.Load (System.Type viewModelType, MvvmCross.Core.ViewModels.IMvxBundle parameterValues, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00000] in :0 --- End of inner exception stack trace --- at MvvmCross.Core.ViewModels.MvxDefaultViewModelLocator.Load (System.Type viewModelType, MvvmCross.Core.ViewModels.IMvxBundle parameterValues, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00029] in :0 at MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00035] in :0 --- End of inner exception stack trace --- at MvvmCross.Core.ViewModels.MvxViewModelLoader.LoadViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00068] in :0 at MvvmCross.iOS.Views.MvxViewControllerExtensionMethods.LoadViewModel (MvvmCross.iOS.Views.IMvxIosView iosView) [0x0005f] in <6f99728979034e579bc72f6d53e5bc35>:0 at MvvmCross.Core.Views.MvxViewExtensionMethods.OnViewCreate (MvvmCross.Core.Views.IMvxView view, System.Func`1[TResult] viewModelLoader) [0x00012] in :0 at MvvmCross.iOS.Views.MvxViewControllerExtensionMethods.OnViewCreate (MvvmCross.iOS.Views.IMvxIosView iosView) [0x00001] in <6f99728979034e579bc72f6d53e5bc35>:0 at MvvmCross.iOS.Views.MvxViewControllerAdapter.HandleViewDidLoadCalled (System.Object sender, System.EventArgs e) [0x00007] in <6f99728979034e579bc72f6d53e5bc35>:0 at at (wrapper delegate-invoke) :invoke_void_object_EventArgs (object,System.EventArgs) at MvvmCross.Platform.Core.MvxDelegateExtensionMethods.Raise (System.EventHandler eventHandler, System.Object sender) [0x00003] in <6adc0d5857264558a9d45778a78ae02a>:0 at MvvmCross.Platform.iOS.Views.MvxEventSourceViewController.ViewDidLoad () [0x00006] in <4467c42ffcc4478e847227b8e4af47fe>:0 at MvvmCross.iOS.Views.MvxViewController.ViewDidLoad () [0x00001] in <6f99728979034e579bc72f6d53e5bc35>:0 at iManage.iOS.Views.LoginView.ViewDidLoad () [0x00001] in /Users/pankajsachdeva/Projects/iManage/iOS/Views/LoginView.cs:18 at at (wrapper managed-to-native) UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr) at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Users/builder/data/lanes/5665/f70a1348/source/xamarin-macios/src/UIKit/UIApplication.cs:79 at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Users/builder/data/lanes/5665/f70a1348/source/xamarin-macios/src/UIKit/UIApplication.cs:63 at iManage.iOS.Application.Main (System.String[] args) [0x00001] in /Users/pankajsachdeva/Projects/iManage/iOS/Main.cs:17



从ViewModel代码:
public class SchoolSelectionViewModel : BaseViewModel
{
private readonly ISchoolNames _schoolService;
public SchoolSelectionViewModel(ISchoolNames schoolService)
{
_schoolService = schoolService;
}
public override void Start()
{
IsLoading = true;
_schoolService.GetFeedItems(OnDilbertItems, OnError);
}

private void OnDilbertItems(List<SchoolModel> list)
{
IsLoading = false;
Items = list;
}

private void OnError(Exception error)
{
// not reported for now
IsLoading = false;
}

private List<SchoolModel> _items = new List<SchoolModel>();
public List<SchoolModel> Items
{
get { return _items; }
set { _items = value; RaisePropertyChanged(() => Items); }
}
private MvxCommand<SchoolModel> _itemSelectedCommand;
public ICommand ItemSelectedCommand
{
get
{
_itemSelectedCommand = _itemSelectedCommand ?? new MvvmCross.Core.ViewModels.MvxCommand<SchoolModel>(DoSelectItem);
return _itemSelectedCommand;
}
}

private void DoSelectItem(SchoolModel item)
{
//ShowViewModel<LoginViewModel>(item);
ShowViewModel<LoginViewModel>(new LoginViewModel(item));
}
}

要查看模型代码:
public class LoginViewModel : BaseViewModel
{
private readonly ILoginService _loginService;

private readonly IDialogService _dialogService;

public LoginViewModel(SchoolModel item)
{
//_loginService = loginService;
//_dialogService = dialogService;
School = item;
Username = "TestUser";
Password = "YouCantSeeMe";
IsLoading = false;
}

private SchoolModel _school;
public SchoolModel School
{
get
{
return _school;
}

set
{
SetProperty(ref _school, value);
RaisePropertyChanged(() => School);
}
}

private string _username;
public string Username
{
get
{
return _username;
}

set
{
SetProperty(ref _username, value);
RaisePropertyChanged(() => Username);
}
}

private string _password;
public string Password
{
get
{
return _password;
}

set
{
SetProperty(ref _password, value);
RaisePropertyChanged(() => Password);
}
}

private IMvxCommand _loginCommand;
public virtual IMvxCommand LoginCommand
{
get
{
_loginCommand = _loginCommand ?? new MvxCommand(AttemptLogin, CanExecuteLogin);
return _loginCommand;
}
}

private void AttemptLogin()
{
if (_loginService.Login(Username, Password))
{
ShowViewModel<DashboardStdViewModel>();
}
else
{
_dialogService.Alert("We were unable to log you in!", "Login Failed", "OK");
}
}

private bool CanExecuteLogin()
{
return (!string.IsNullOrEmpty(Username) || !string.IsNullOrWhiteSpace(Username))
&& (!string.IsNullOrEmpty(Password) || !string.IsNullOrWhiteSpace(Password));
}
}

编辑1:
在我从ViewModel修改以下内容:
        private async void DoSelectItem(SchoolModel item)
{
await _navigationService.Navigate<LoginViewModel,SchoolModel>(item);
}

更改了下一个ViewModel声明,如下所示:
public class LoginViewModel : MvxViewModel<SchoolModel>

当我尝试显示带有以下错误的下一个viewmodel时,它仍然崩溃:
你调用的对象是空的。
编辑2:
完成错误:

System.NullReferenceException: Object reference not set to an instance of an object at iManage.ViewModels.SchoolSelectionViewModel+d__19.MoveNext () [0x0000f] in /Users/pankajsachdeva/Projects/iManage/iManage/ViewModels/SchoolSelectionViewModel.cs:67 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.3/src/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:152 at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.b__6_0 (System.Object state) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.3/src/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1018 at UIKit.UIKitSynchronizationContext+c__AnonStorey0.<>m__0 () [0x00000] in /Users/builder/data/lanes/5665/f70a1348/source/xamarin-macios/src/UIKit/UIKitSynchronizationContext.cs:24 at Foundation.NSAsyncActionDispatcher.Apply () [0x00000] in /Users/builder/data/lanes/5665/f70a1348/source/xamarin-macios/src/Foundation/NSAction.cs:163 at at (wrapper managed-to-native) UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr) at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Users/builder/data/lanes/5665/f70a1348/source/xamarin-macios/src/UIKit/UIApplication.cs:79 at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Users/builder/data/lanes/5665/f70a1348/source/xamarin-macios/src/UIKit/UIApplication.cs:63 at iManage.iOS.Application.Main (System.String[] args) [0x00001] in /Users/pankajsachdeva/Projects/iManage/iOS/Main.cs:17

最佳答案

MvvmCross.Platform.Exceptions.MvxIoCResolveException: Failed to resolve parameter for parameter item of type SchoolModel when creating iManage.ViewModels.LoginViewModel at MvvmCross.Platform.IoC.MvxSimpleIoCContainer.GetIoCParameterValues (System.Type type, System.Reflection.ConstructorInfo firstConstructor)



问题在于 SchoolModel的构造函数中使用的参数 LoginViewModel的类型。尝试构造 MvxSimpleIoCContainer时, LoginViewModel无法解析类型。

所以我要谈两点
  • 通过查看MvvmCross如何构造 View 模型,为什么会遇到此异常。
  • 如何在MvvmCross 5生命周期中使用navigation service introduced in MvvmCross 5和传统ShowViewModel在 View 模型之间传递参数。


  • 在MvvmCross中查看模型IoC使用情况

    MvvmCross view models are constructed via IoC中。这意味着 View 模型类的公共(public)构造函数的参数需要向IoC容器注册,以便容器构造该类。

    用作构造参数的类型也很重要,因为默认情况下MvvmCross使用 Service Locator pattern支持仅针对实现类型注册的接口(interface)类型。针对实现类型 Foo和接口(interface)类型 IFoo注册的示例。
    Mvx.ConstructAndRegisterSingleton<IFoo, Foo>();

    由于MvvmCross对 View 模型使用了构造函数注入(inject),因此无法将 View 模型类的公共(public)构造函数用于传递给 View 模型类实例的参数。构造函数参数必须能够来自IoC容器。

    MvvmCross在 View 模型之间传递5个参数(Navigation Service)

    MvvmCross 5 the Navigation Service中,它是在MvvmCross中编写导航逻辑的首选方法。导航服务还提供一种在 View 模型之间传递参数的方法,以避免通过 View 模型构造函数传递参数。 MvvmCross documentation中有一个很好的示例,显示了如何传递参数。这是摘录
    public class MyViewModel : MvxViewModel
    {
    private readonly IMvxNavigationService _navigationService;

    public MyViewModel(IMvxNavigationService navigationService)
    {
    _navigationService = navigationService;
    }

    public async Task SomeMethod()
    {
    await _navigationService.Navigate<NextViewModel, MyObject>(new MyObject());
    }
    }

    public class NextViewModel : MvxViewModel<MyObject>
    {
    private MyObject _myObject;

    public override void Prepare(MyObject parameter)
    {
    // receive and store the parameter here
    _myObject = parameter;
    }
    }

    快速说明。从 NextViewModel( View 模型导航)开始,您需要在继承的 MvxViewModel基类泛型中指定要传递的参数的类型,然后重写 Prepare来传递参数。在 MyViewModel方法的调用类 navigate中,您包括导航到的 View 模型的类型以及要传递的参数的类型。然后,将参数作为 navigate方法的第一个参数传递。

    在 View 模型(ShowViewModel)之间传递参数

    在示例代码中,您仍在使用较旧的 ShowViewModel模式进行导航,因此我将介绍如何使用 ShowViewModel方法传递参数。有关传递 ShowViewModel参数的MvvmCross文档,可以找到 here for the complex parameter objecthere for the simple parameter object

    复杂参数对象

    对于复杂的参数对象,MvvmCross要求您已安装MvvmCross Json插件。这种方法将序列化和反序列化通过的参数
    public class SchoolSelectionViewModel : BaseViewModel
    {
    public void DoSelectItem(SchoolModel item)
    {
    ShowViewModel<LoginViewModel, SchoolModel>(item);
    }
    }

    public class LoginViewModel : BaseViewModel<SchoolModel>
    {
    private SchoolModel _parameter;

    public override Task Prepare(SchoolModel parameter)
    {
    // receive and store the parameter here
    _parameter = parameter;
    }
    }

    如果您无法继承 IMvxViewModel<TParameter>LoginViewModel,则可能还需要使用 MvxViewModel<TParameter>契约实现自定义基类。
    public abstract class BaseViewModel<TParameter> : BaseViewModel, IMvxViewModel<TParameter>
    {
    public async Task Init(string parameter)
    {
    if (!string.IsNullOrEmpty(parameter))
    {
    IMvxJsonConverter serializer;
    if (!Mvx.TryResolve(out serializer))
    {
    throw new MvxIoCResolveException("There is no implementation of IMvxJsonConverter registered. You need to use the MvvmCross Json plugin or create your own implementation of IMvxJsonConverter.");
    }

    var deserialized = serializer.DeserializeObject<TParameter>(parameter);
    Prepare(deserialized);
    await Initialize();
    }
    }

    public abstract void Prepare(TParameter parameter);
    }

    简单参数对象

    对于不需要序列化的基本类型,可以使用此方法,但会损失类型安全性参数。
    public class SchoolSelectionViewModel : BaseViewModel
    {
    public void DoSelectItem(SchoolModel item)
    {
    ShowViewModel<LoginViewModel>(item);
    }
    }

    public class LoginViewModel : BaseViewModel
    {
    private SchoolModel _parameter;

    public override void Init(SchoolModel parameter)
    {
    // receive and store the parameter here
    _parameter = parameter;
    }
    }

    注意用于Simple参数对象的类型的规则

    此处使用的类必须是仅用于以下导航的“简单”类:
  • 它必须包含无参数构造函数
  • 它应仅包含具有getset访问权限的公共(public)属性
  • 这些属性只能是以下类型:
  • bool
  • 整数类型:sbyteshortintlongbyteushortuintulong
  • 浮点类型:floatdouble
  • decimal
  • char
  • string
  • DateTime
  • Guid
  • 枚举值


  • 最后说明

    在早期版本的MvvmCross v5.x.x中,对 View 模型生命周期进行了一些更改,但是从 v5.5+开始,上述模式应适用。

    关于c# - 从 View 模型导航到mvvmcross中的另一个 View 模型时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48252248/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com