MvvmCross - Failed to resolve type for ViewModel

2019-05-23 05:13发布

问题:

This is related to another question I posted but probably warrants its own.

I need to be able to execute a Command in my ViewModel from its related Android View and specifically when an Action Bar menu item is clicked. Therefore, first of all I need access to the instance of the ViewModel.

Firstly I tried the following line of code in the OnCreateOptionsMenu(IMenu menu) method of the View:

NewJobViewModel newJobViewModel = Mvx.Resolve<NewJobViewModel>();

However, this caused the error: "UNHANDLED EXCEPTION: Cirrious.CrossCore.Exceptions.MvxException: Failed to resolve type MyProject.Core.ViewModels.NewJobViewModel"

I then tried this instead:

[Activity]
public class NewJobView : MvxActivity {
    private NewJobViewModel _newJobViewModel;

    public NewJobViewModel NewJobViewModel {
        get { return _newJobViewModel; }
        set { _newJobViewModel = value; }
    }

    protected override void OnCreate(Bundle bundle) {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.NewJobView);
        this.NewJobViewModel = Mvx.Resolve<NewJobViewModel>();
    }
}

...which didn't help.

However, adding the following to Apps.cs cured the error but caused other issues as it clearly hadn't given me the same instance of the ViewModel that the MvvmCross framework must have already initialised in the background(?):

public override void Initialize() {
    CreatableTypes()
        .EndingWith("NewJobViewModel")
        .AsTypes()
        .RegisterAsSingleton();
}

I clearly misunderstand some of the architecture and what's happening in the background (so I apologise if this is a basic question) but can someone please tell me what I'm doing wrong?

回答1:

MvvmCross automatically wires up your View and ViewModel for you.

This happens automatically during the call to base.OnCreate(bundle);

If you want to access your ViewModel within your View you can do this using the ViewModel property.

However, since the ViewModel property is defined in a shared base class, it is of type IMvxViewModel

To get a typed ViewModel you can simply cast it to your specific type - e.g.

 var myTypedView = (MyTypedViewModel)ViewModel;

You definitely don't want to create a new viewmodel (which is what Mvx.Resolve<NewJobViewModel>() tries to do) - instead you just want access to the current one.