Navigate between views in Xamarin iOS using MVVM Light

Hi again, let’s move on to the second post under Xamarin category. We will use the project that we have configured in our earlier post as our basement, where we have integrated MVVM Light NuGet packages. What we are going to do is, navigating between some view controllers and understand how MVVM Light works.

Just like the routine, I’ll start by showing what you can see once you completed this project and run it on your device.

AnujAroshA_Xamarin_MVVMLight

We have three pages and we are trying to navigate among those pages with button events and mean time update labels on those views. Now we dig into code.

One of the main thing that we need to do is create a reference to the ViewModelLocator that has been created. We do it inside our Main.cs file, like below.

public static ViewModelLocator Locator
{
    get
    {
        return locator ?? (locator = new ViewModelLocator());
    }
}

ViewModelLocator is the class which tells the views to where its corresponding view model class are located. Basically, every MVVM Light project does contain one ViewModelLocator class. To explain the usage of that class, I’ll take MainViewController as an example. Since we are using storyboard to create the view, our view controller is already linked with the view. What we need to do is link the ViewModel part, which we are doing like this.

private MainViewModel Vm
{
    get
    {
        return Application.Locator.Main;
    }
}

As you can see, the MainViewModel class, which has been created, got referred inside the Controller class. It is a private reference, since other views does not need to directly involve with someone else’s view model.  Let’s see how we have registered the view  models inside the ViewModelLocator. First we register it inside the ViewModelLocator class constructor.

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

    SimpleIoc.Default.Register<MainViewModel>();
}

Just like mentioned in the code, we are using an Inversion Of Control that has provided by default by the MVVM Light. Next we are creating a public reference to that MainViewModel.

public MainViewModel Main
{
    get
    {
        return ServiceLocator.Current.GetInstance<MainViewModel>();
    }
}

At this moment, we have a view controller (MainViewController) that linked to its view (Main.storyboard) and also linked to its ViewModel (MainViewModel) via a locator (ViewModelLocator). What we need now is another view controller and a way to navigate from first view controller to the second. You can create another view controller in story board and make sure to give a Storyboard ID for that view controller, because we are going to use it as a reference inside the ViewModelLocator like below.

public const string SecondPageKey = "SecondPage";

In the image that I have posted at the beginning, you can see a button in the first page to navigate to the next page. We need to create an event to that button to execute a command. This is how we are going to do that. Inside the MainViewModel we create a RelayCommand.

public RelayCommand NavigateCommand
{
    get
    {
        return navigateCommand ?? (navigateCommand = new RelayCommand(() => navigationService.NavigateTo(ViewModelLocator.SecondPageKey)));
    }
}

Then  add an event to the button inside the view controller.

NavigateButton.TouchUpInside += (s, e) =>
{
    Vm.NavigateCommand.Execute(null);
};

NavigateButton is the Name that we have given to that button as an Identity in the storyboard. But you may wonder where on the earth that navigateCommand and navigationService variables appeared. Those variables, I have created in the MainViewModel and also MainViewModel constructor is loaded with INavigationService like below.

private RelayCommand navigateCommand;
private readonly INavigationService navigationService;

public MainViewModel(INavigationService navigationService)
{
    this.navigationService = navigationService;
}

Before you try to run the application and move from one view to another, we have one more work to do inside the AppDelegate class. That is initialize MVVM Light’s DispatcherHelper for cross-thread handling and configure and register the MVVM Light NavigationService.

public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
    DispatcherHelper.Initialize(application);

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

    nav.Initialize((UINavigationController)Window.RootViewController);
    nav.Configure(ViewModelLocator.SecondPageKey, "SecondPage");
    nav.Configure(ViewModelLocator.ThirdPageKey, "ThirdPage");

    return true;
}

Finally what remains for us is to figure out how binding is work between view element and the view model. I’ll show it using the label that I have created in the second page. Here I would like to emphasis one thing. For a project, there will be one ViewModelLocator but there will be several ViewModel classes depend on the Views that you are going to have. I believe now you can create a ViewModel class for the SecondViewController and link them together using ViewModelLocator.

Back to the binging data to the view element in SecondViewController. Inside the SecondViewModel, I have created a string property that will contain the text which should display in the label when the second page loads.

private string navInfoStatus;

public SecondViewModel(INavigationService navihationService)
{
    // More code here
    NavInfoStatus = "Haven't moved to third view";
}

public string NavInfoStatus
{
    get => navInfoStatus;
    set => Set(ref navInfoStatus, value);
}

Data binding can be happen between two properties, That’s one of the reason I had to create a string property that contains the value for the label. So obviously the other property is the label text. I did the binding inside the ViewDidLoad() method in SecondViewController like this.

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

    this.SetBinding(() => SecondVm.NavInfoStatus, () => NavInfoLabel.Text);

    // More code goes here
}

Before wrap up things, would like to show you the usage of => in C#. There are two main purposes of using that operator.

  1. As lambda operator
  2. Expression body definition

Here is an example of using => operator as a lambda operator

bindings.Add(this.SetBinding(() => Vm.WelcomeTitle, () => WelcomeText.Text));

and here is an example of using it as expression body definition.

public SecondViewModel Second => ServiceLocator.Current.GetInstance<SecondViewModel>();

I think we have enough content for this blogpost. Those who have authorized can see the full source code here. Until we meet again Mahalo… 🙂

 

 

Advertisements

About AnujAroshA

Working as an Associate Technical Lead. Specialized in iOS application development. A simple person :)
This entry was posted in iOS, MVVM, Xamarin and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s