I've spent the last few days trying to figure out a way to get around the warning:
mvx: Warning: 8.93 Exception masked MissingMethodException: Default constructor not found for type FCX.iOS.TimesheetView
at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00094] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System/Activator.cs:326
at System.Activator.CreateInstance (System.Type type) [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System/Activator.cs:222
at Cirrious.MvvmCross.Touch.Views.MvxTouchViewsContainer.CreateView (Cirrious.MvvmCross.ViewModels.MvxViewModelRequest request) [0x00000] in :0
at Cirrious.MvvmCross.Touch.Views.MvxCanCreateTouchViewExtensionMethods.CreateViewControllerFor (IMvxCanCreateTouchView view, Cirrious.MvvmCross.ViewModels.MvxViewModelRequest request) [0x00000] in :0
at Cirrious
.MvvmCross.Touch.Views.Presenters.MvxTouchViewPresenter.Show (Cirrious.MvvmCross.ViewModels.MvxViewModelRequest request) [0x00000] in :0
at Cirrious.MvvmCross.Touch.Views.MvxTouchViewDispatcher+<>c__DisplayClass4.b__3 () [0x00000] in :0
at Cirrious.CrossCore.Core.MvxMainThreadDispatcher.ExceptionMaskedAction (System.Action action) [0x00000] in :0
It appears the navigation is looking for this constructor:
public TimesheetView ()
{
}
When I WANT it to use this constructor (for storyboard purposes):
public TimesheetView (IntPtr handle) : base (handle)
{
}
I've been trying to bind a button from one view to the following ICommand:
private MvxCommand _NewTimesheetCommand;
public ICommand NewTimesheetCommand
{
get
{
_NewTimesheetCommand = _NewTimesheetCommand ?? new MvxCommand(() => {
ShowViewModel<TimesheetViewModel>(new TimesheetViewModel.Parameters { Mode = TimesheetViewModel.ModeEnum.ADD });
});
return _NewTimesheetCommand;
}
}
After looking at many StackOverFlow questions, I came across this question, but it almost sounds that using storyboards REQUIRES me to use segues (in other words there isn't a way to use ICommand to change my view).
Does MvvmCross support storyboards
My main question: Is it possible to use storyboards and change the view with the viewmodel? (rather than using segues from the view)
Hmmm I just implemented what Stuart said. Works great. (Do remember that segue's are useless this way you navigate using ShowViewModel inside the viewmodels)
using System;
using Cirrious.MvvmCross.Touch.Views.Presenters;
using MonoTouch.UIKit;
using MonoTouch.Foundation;
using Cirrious.MvvmCross.Touch.Views;
using Cirrious.MvvmCross.ViewModels;
namespace DigitalCatalog.UI.Touch
{
public class StoryBoardTouchViewPresenter : MvxTouchViewPresenter
{
public static UIStoryboard Storyboard = null;
public StoryBoardTouchViewPresenter (UIApplicationDelegate applicationDelegate, UIWindow window, string storyboardName, NSBundle StoryboardBundleOrNull = null) : base(applicationDelegate, window)
{
Storyboard = UIStoryboard.FromName (storyboardName, StoryboardBundleOrNull);
}
public override void Show (IMvxTouchView view)
{
MvxViewController sbView = null;
try{
sbView = (MvxViewController) Storyboard.InstantiateViewController (view.Request.ViewModelType.Name.Replace("Model", ""));
}catch(Exception e){
Console.WriteLine ("Failed to find storyboard view, did you forget to set the Storyboard ID to the ViewModel class name without the Model suffix ?" + e);
}
sbView.Request = view.Request;
base.Show (sbView);
}
}
}
All you have to do now is set the AppDelegate like this :
public override void FinishedLaunching (UIApplication application)
{
StoryBoardTouchViewPresenter sbPresenter = new StoryBoardTouchViewPresenter(this, Window,"MainStoryboard_iPad");
var setup = new Setup(this,sbPresenter);
setup.Initialize();
var startup = Mvx.Resolve<IMvxAppStart>();
startup.Start();
sbPresenter.MasterNavigationController.NavigationBar.Translucent = false;
sbPresenter.MasterNavigationController.SetNavigationBarHidden(false, false);
}
LAST REMEMBER TO SET FOR EVERY VIEW IN THE STORYBOARD A STORYBOARD ID WITH THE "CLASS NAME" OF THE VIEW !!!! sadly there isn't any other way to get a view using the UIStoryboard class you can only get it by using Storyboard Ids
There are ways to load a `UiViewController. From a storyboard - eg see load view form StoryBoard that does not have a Segue
If you want to use this custom loading in mvvmcross, then you could override the IMvxTouchViewCreator
so that it uses this sort of storyboard load, or you could override the presenter
so that it loads the storyboard view directly .
Overall, though, it feels like you are fighting against storyboards if you are working this way - almost all storyboard navigation seems to be segue based. With this in mind another thing you could do is to implement a custom presenter and to get that presenter to convert ShowViewModel requests into performSegueWithIdentifier
calls.