[MVVMbasics] UWP with MVVMbasics: IBindableView, x:Bind and async Commands

All blog posts with a title that starts with [MVVMbasics] are related to the MVVMbasics framework. If you are only interested in my regular blog posts and not in MVVMbasics, ignore these. To list all articles covering MVVMbasics, go to http://mvvmbasics.mobilemotion.eu/documentation!

Since version 2.3 of the MVVMbasics framework finally supports Universal Windows Apps for Windows 10 (UWP platform), I’d like to summarize the new features (apart from bug fixes) in this release. Let’s start with those that are only available to Windows 10 projects:

The IBindableView interface:

In addition to inheriting from BaseView, each View should now implement the IBindableView interface. This interface expects one generic parameter, which is the type of Viewmodel that shall be assigned to the View as DataContext. There are three reasons why you should use IBindableView:

  • In older versions, Views are marked with the [MvvmNavigationTarget] attribute to assign the appropriate Viewmodel type. When implementing IBindableView, this is done automatically (NavigatorService will create a Viewmodel instance when navigating to the View, and register it as DataContext) and the [MvvmNavigationTarget] attribute can be omitted (although no bad things will happen if specifying both [MvvmNavigationTarget] and IBindableView):
    public sealed partial class MyPage : BaseView, IBindableView<MyViewmodel>
    {
        // ...
    }
    
  • One of the major new features of Windows 10 UWP, compiled bindings, is now also supported by MVVMbasics: Implementing the IBindableView forces you to define a public property Vm in your View, which will automatically be filled with the current Viewmodel instance at startup and whenever the View’s DataContext changes. This means, you can simply use the Vm property for binding:
    <TextBox Text="{x:Bind Vm.SomeTextProperty, Mode=TwoWay}"/>
    <TextBox Text="{Binding SomeTextProperty, Mode=TwoWay}"/>
    

    Of course, also DataContext always contains the current Viewmodel instance and can still be used for binding in case you don’t want to use compiled bindings.

  • An additional advantage of specifying the Vm property is that it can be used to access the Viewmodel (e.g., invoke Commands) from View code-behind in an easier way than using the old Viewmodel property (no need to cast to the actual Viewmodel type any more), therefore the BaseView.Viewmodel property is now marked deprecated.
    public sealed partial class MyPage : BaseView, IBindableView<MyViewmodel>
    {
        private void Button_OnClick(object sender, RoutedEventArgs e)
    	{
    		var viewmodel = this.Viewmodel as MyViewmodel; // These 3 lines
    		if (viewmodel != null)                         // are not necessary
    			viewmodel.SomeCommand.Execute();           // any more
    		
    		// Much simpler:
    		Vm.SomeCommand.Execute();
    	}
    }
    

Asynchronous commanding:

Another new feature of the 2.3.0 version is the support of asynchronous commands for all platforms (not just Windows 10 UWP). The BaseCommand class provides four new constructor overloads that allow passing asynchronous methods (with return type of Task instead of void) as execute action. Accordingly, from within Viewmodels you can simply call one of the four CreateAsyncCommand method overloads, that create and return an asyncronous BaseCommand instance.

When an async command is called from the UI (e.g., by clicking a button that binds to this Command which internally calls the Command’s Execute method), the MVVMbasics framework takes care of invoking the async method and awaiting it, and you won’t ever notice it. The advantage of those asynchronous Commands over conventional Commands is that they provide an additional ExecuteAsync method provides a return type of Task. When testing such a Command from within a unit test, you might want to call this ExecuteAsync method instead of the traditional Execute method, since this allows you to await the method’s execution.