Search code examples
dependency-injectionxamarin.iosinversion-of-controlxamarinmvvmcross

IOC not resolving dependencies - MVVMCross


I'm a complete newbie to MVVMCross but I'm trying to get the dependencies working using monotouch and Xamarin Studio with latest binaries of MVVMCross from github.

Can't really find tutorials dedicated to Xamarin Studio + Monocross so after cobbling together some tutorials I have some trivial controls wonderfully working. Then I attempted to embark on some map features and a sprinkle of DI. Unfortunately, I get errors saying the dependencies could not be resolved. Where am I going wrong?

// my view model
using System;
using Cirrious.MvvmCross.Plugins.Location;
using Cirrious.MvvmCross.ViewModels;
using Cirrious.CrossCore;

namespace mvxTest.Core
{

    public class MapViewModel : MvxViewModel
   {
            private IMvxLocationWatcher _watcher;

            public MapViewModel (IMvxLocationWatcher watcher) 
            {
                  // var resolved = Mvx.CanResolve<IMvxLocationWatcher> ();  // returns false
                  _watcher.Start (new MvxLocationOptions (), OnSuccess, OnError);
            }
    }
}



// my view
using System;
using Cirrious.MvvmCross.Touch.Views;
using MonoTouch.UIKit;
using System.Drawing;
using Cirrious.MvvmCross.Binding.BindingContext;
using mvxTest.Core;

namespace mvxTest.Touch
{

 // http://www.youtube.com/watch?v=MM9iQlx3quA
public class MapView : MvxViewController
{
    public MapView ()
    {
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();  // <-- breaks here with complaints 

        var label = new UILabel (new RectangleF (0, 100, 100, 50));
        label.BackgroundColor = UIColor.Blue;
        Add (label);

        var edit = new UITextView (new RectangleF (0, 200, 100, 50));
        edit.BackgroundColor = UIColor.Green;
        Add (edit);

        var binding = this.CreateBindingSet<MapView, MapViewModel> ();
        binding.Bind (label).To ((v) => v.Lat);
        binding.Bind (edit).To ((v) => v.Lng);
        binding.Apply ();
    }
}
}

Error is confusing as it mentions viewmodel dependency not resolving but the error is thrown in the view when viewdidload event is triggered. Maybe its where view model is loaded. Anyhow why isnt the dependencies injected - I suspect the plugin somehow needs to be registered in monotouch project.

2013-10-31 21:45:21.291 mvxTestTouch[9806:80b] mvx: Diagnostic:   0.20 Showing ViewModel MapViewModel
2013-10-31 21:45:21.294 mvxTestTouch[9806:80b] TouchNavigation: Diagnostic:   0.20 Navigate requested
2013-10-31 21:45:21.400 mvxTestTouch[9806:80b] mvx: Warning:   0.31 Problem creating viewModel of type MapViewModel - problem MvxException: Failed to resolve parameter for parameter watcher of type IMvxLocationWatcher when creating mvxTest.Core.MapViewModel
 at Cirrious.CrossCore.IoC.MvxSimpleIoCContainer.GetIoCParameterValues (System.Type type, System.Reflection.ConstructorInfo firstConstructor) [0x00000] in <filename unknown>:0 
 at Cirrious.CrossCore.IoC.MvxSimpleIoCContainer.IoCConstruct (System.Type type) [0x00000] in <filename unknown>:0 
 at Cirrious.CrossCore.Mvx.IocConstruct (System.Type t) [0x00000] in <filename unknown>:0 
 at Cirrious.MvvmCross.ViewModels.MvxDefaultViewModelLocator.TryLoad (System.Type viewModelType, IMvxBundle parameterValues, IMvxBundle savedState, IMvxViewModel& viewModel) [0x00000] in <filename unknown>:0 

// UPDATE

thanks for the suggestions stuart - after watching N31 + N8 + bits of N9, I've included a LocationPluginBootstrap in the touch project and sharing same namespace, and it works great - THANKS!!:

using Cirrious.CrossCore.Plugins;
using Cirrious.MvvmCross.Plugins.Location;
using Cirrious.MvvmCross.Plugins.Location.Touch;

namespace mvxTest.Touch
{
   public class LocationPluginBootstrap
    : MvxLoaderPluginBootstrapAction<PluginLoader,Plugin>
   {
   }
}

Solution

  • IMvxLocationWatcher is an optional component - located in a plugin.

    To make the plugin available, you'll need to reference the plugin core and touch assemblies, and you'll need to include a bootstrap class - like https://github.com/MvvmCross/NPlus1DaysOfMvvmCross/blob/master/N-08-Location/Location.Touch/Bootstrap/LocationPluginBootstrap.cs

    For more on plugins and the in depth story of how they are initialised, see https://github.com/MvvmCross/MvvmCross/wiki/MvvmCross-plugins