xplat
xplat

Reputation: 8636

MvvmLight unable to create a controller for key

I am designing a cross platform application architecture using Xamarin iOS and Xamarin Android I decided to go with MvvmLight, it looks descent and is not hiding everything from the MVVM pattern, good and flexible. While everything started to make sense trying to set it up and learn how to use it, I find myself difficult to understand why I get the following error.

Unable to create a controller for key ChartsPage

The setup.

In a PCL I have my ViewModels. I have a ViewModelLocator setup. I use the mvvmlightlibs Nuget Package.

public class ViewModelLocator
    {
        public static readonly string SchedulerPageKey = @"SchedulerPage";
        public static readonly string ChartsPageKey = @"ChartsPage";

        [SuppressMessage("Microsoft.Performance",
            "CA1822:MarkMembersAsStatic",
            Justification = "This non-static member is needed for data binding purposes.")]
        public SchedulerViewModel Scheduler
        {
            get
            {
                return ServiceLocator.Current.GetInstance<SchedulerViewModel>();
            }
        }

        public BizchartsViewModel Bizcharts
        {
            get
            {
                return ServiceLocator.Current.GetInstance<BizchartsViewModel>();
            }
        }

        static ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            if (ViewModelBase.IsInDesignModeStatic)
            {
//              Haven't declared something yet
            }
            else
            {
//              Haven't declared something yet
            }

            SimpleIoc.Default.Register<SchedulerViewModel>();
            SimpleIoc.Default.Register<BizchartsViewModel>();
        }
    }

The I have a unified iOS application using universal storyboard with size classes which has an initial UINavigationViewController SchedulerViewController and in the ViewDidLoad method I test the navigation to BizchartsViewController with 3 seconds delay. After 3 seconds I get the exceptions.

In the AppDelegate.

private static ViewModelLocator _locator;
        public static ViewModelLocator Locator
        {
            get
            {
                if (_locator == null)
                {
                    SimpleIoc.Default.Register<IDialogService, DialogService>();

                    _locator = new ViewModelLocator();
                }

                return _locator;
            }
        }
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            var nav = new NavigationService();
            nav.Initialize((UINavigationController)Window.RootViewController);
            nav.Configure(ViewModelLocator.ChartsPageKey, typeof(BizchartsViewController));

            SimpleIoc.Default.Register<INavigationService>(() => nav);

            return true;
        }

The SchedulerViewController.

partial class SchedulerViewController : UIViewController
    {
        public SchedulerViewModel Vm {
            get;
            private set;
        }

        public SchedulerViewController (IntPtr handle) : base (handle)
        {
            Vm = AppDelegate.Locator.Scheduler;
        }

        public async override void ViewDidLoad ()
        {
            base.ViewDidLoad ();

            await Task.Delay (3000);
            Vm.NavigateToCharts ();
        }
    }

The SchedulerViewModel.

public class SchedulerViewModel : ViewModelBase
    {
        public void NavigateToCharts()
        {
            var nav = ServiceLocator.Current.GetInstance<INavigationService>();
            nav.NavigateTo(ViewModelLocator.ChartsPageKey);
        }
    }

I definitely miss a detail somewhere!!!

Upvotes: 0

Views: 454

Answers (1)

xplat
xplat

Reputation: 8636

If you follow carefully the blog post here, it says that with Storyboard you should use the string overload and not the typeof() in nav.Configure(Key, ViewController) and always set the storyboardId and restorationId in the Storyboard ViewController.

Note that because we are using a Storyboard, you must make sure to use the Configure(string, string) overload, and NOT the Configure(string, Type) one.

Upvotes: 1

Related Questions