简体   繁体   中英

How to replace MvxDefaultViewModelLocator in MVVMCross application

I'd like to roll my own ViewModelLocator to provide a try/catch/log wrapper for ViewModel creation at a central place within the application, to be able to do it I've to replace the default MvxDefaultViewModelLocator. But I did not find a way to replace the generic one, only to inject a VM type specific one.

How should I inject my own ViewModelLocator class as a default one?

I just reread your question.... and I answered a different one, didn't I? Sorry!

Let's try again...


The default MvxApplication doesn't provide any way to override this member. If you think it would be useful to, then by all means raise an issue or a pull on GitHub.

However, without changing the Mvx code, then one way to achieve the effect that I think you are looking for is to simply replace the IMvxViewModelLocatorFinder interface in the IoC/ServiceProvider framework - you could easily implement:

  public class MyFinder : IMvxViewModelLocatorFinder
  {
        public IMvxViewModelLocator FindLocator(MvxShowViewModelRequest request)
       {

            return new MyDefaultViewModelLocator();
       }
  }

and you could then inject this (overwriting the Application entry in IoC) during the InitializeLastChance part of Setup for each of the client projects?


Alternatively, you could go even higher if you wanted to - you could replace IMvxViewModelLoader instead

This is straight forward to do... but not actually in any of the samples!

The "container" for ViewModelLocators is the MvxApplication object. By default it uses a convention based MvxDefaultViewModelLocator which just tries to construct ViewModel instances by using their declared constructors which have string parameters.

If you would like to use your own ViewModel locator, then the easiest way is simple to inherit from MvxViewModelLocator and to provide either public Properties or public Methods which return your ViewModel instances:

eg:

public class MyViewModelLocator : MvxViewModelLocator
{
    public MyFirstViewModel CreateFirst()
    {
        return new MyFirstViewModel();
    }

    public MySecondViewModel CreateSecond(string aParameter)
    {
        var someLookup1 = ComplicatedStaticThing1.Lookup(aParameter);
        var viewModel = new MySecondViewModel(someLookup1);

        var someLookup2 = ComplicatedStaticThing2.Lookup(aParameter, someLookup1);
        viewModel.DoSomething(someLookup2);

        return viewModel;
    }

    private readonly MyThirdViewModel _third = new MyThirdViewModel();
    public MyThirdViewModel Third
    {
        get
        {
            return _third;
        }
    }
}

If you want to go even lower than this, then you can also implement IMvxViewModelLocator directly instead.

To add the ViewModelLocator to the application, simply instantiate and add it inside your app - eg:

public class App 
    : MvxApplication
    , IMvxServiceProducer<IMvxStartNavigation>
{
    public App()
    {
        this.RegisterServiceInstance<IMvxStartNavigation>(new StartApplicationObject());

        base.AddLocator(new MyViewModelLocator());

        // to disable the default ViewModelLocator, use:
        // base.UseDefaultViewModelLocator = false;
    }
}

Note: - apart from for design time data, I now very rarely find the need to implement custom ViewModelLocator - in general everything I want to do can be done within the ViewModel construction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM