0
votes

I'm trying out MvvmCross with Xamarin 'classic'. I've got it working with Android.

But I can't get it work for iOS. I've taken a look at the sample mentioned here (eh): MVVMCross support for Xamarin.iOS Storyboards

I'm really missing something. What do i have:

  • A storyboard with only 3 controls on it. a label and 2 buttons. All 3 have names so i get the properties in the RootViewController class.
  • The basis setup.cs
  • AppDelegate.cs

    [Register("AppDelegate")]
        public partial class AppDelegate : MvxApplicationDelegate
        {
    
    UIWindow _window;
    
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        _window = new UIWindow(UIScreen.MainScreen.Bounds);
    
        StoryBoardTouchViewPresenter sbPresenter = new StoryBoardTouchViewPresenter(this, _window, "MainStoryboard");
    
        var setup = new Setup(this, _window);
        setup.Initialize();
    
        var startup = Mvx.Resolve<IMvxAppStart>();
        startup.Start();
    
        sbPresenter.MasterNavigationController.NavigationBar.Translucent = false;
    
        sbPresenter.MasterNavigationController.SetNavigationBarHidden(false, false);
    
        return true;
    }
    
    }
    

StoryBoardTouchViewPresenter (from MVVMCross: Is it possible to use Storyboard with ICommand navigation?) But the API is changed.

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);
    }

}

The default App.cs in the Core project

public class App : Cirrious.MvvmCross.ViewModels.MvxApplication
    {
        public override void Initialize()
        {
            CreatableTypes()
                .EndingWith("Service")
                .AsInterfaces()
                .RegisterAsLazySingleton();

            RegisterAppStart<ViewModels.MainViewModel>();
        }
    }

The ViewModel:

public class MainViewModel : MvxViewModel
    {
        ITodoTaskService taskService;
        IDataManager<TodoTask> tasks;

        public MainViewModel(ITodoTaskService taskService)
        {
            this.taskService = taskService;
        }

        public async override void Start()
        {
            this.tasks = new DataManager<TodoTask>(await this.taskService.GetTodoTasksAsync());
            this.tasks.MoveFirst();

            Rebind();
            base.Start();
        }

        private void Rebind()
        {
            this.Description = this.tasks.Current.Description;

            NextCommand.RaiseCanExecuteChanged();
            PreviousCommand.RaiseCanExecuteChanged();
        }

        private string description;

        public string Description
        {
            get { return this.description; }
            set
            {
                this.description = value;
                RaisePropertyChanged(() => Description);
            }
        }   

        private MvxCommand nextCommand;
        public MvxCommand NextCommand
        {
            get
            {
                this.nextCommand = this.nextCommand ?? new MvxCommand(NavigateToNext, CanNavigateNext);
                return this.nextCommand;
            }
        }

        private bool CanNavigateNext()
        {
            return this.tasks.CanMoveNext;
        }

        public void NavigateToNext()
        {
            this.tasks.MoveNext();
            Rebind();
        }

        private MvxCommand previousCommand;
        public MvxCommand PreviousCommand
        {
            get
            {
                this.previousCommand = this.previousCommand ?? new MvxCommand(NavigateToPrevious, CanNavigatePrevious);
                return this.previousCommand;
            }
        }

        private bool CanNavigatePrevious()
        {
            return this.tasks.CanMovePrevious;
        }

        public void NavigateToPrevious()
        {
            this.tasks.MovePrevious();
            Rebind();
        }
    }

I tried all kind of things. At the moment i get an exception that the MainView cannot be found. Which i partly understand. in App.cs MainViewModel is the start up. But the controller is called RootViewController. I think the RootviewController should bind to my MainViewModel. But i don't know how.

How should I make MvvmCross with iOs working? How should I name the parts?

1

1 Answers

0
votes

MvvmCross' default view finder will look for a view called MainView. That view should be derived from MvxViewController or another IMvxTouchView type. If you don't want to name your view controller "MainView" then you need to create a custom view resolver.

My advice: just rename your RootViewController to MainView.