Prism Forms 6.3.0 Highlights

For those following Prism 6.3, it's been a while coming, but there is a lot there. Here are a few helpful things to get you going.

 

Behaviors

One of my favorite additions to Prism Forms 6.3.0 is the addition of Behaviors. First of all Prism gives you a great BehaviorBase<T> class you can use for all of your custom behaviors. But we finally have an EventToCommandBehavior that allows us to execute our ViewModel Commands when an event is triggered, and the control doesn't directly support Commands for that event. This is great for things like attaching to something like a ListView where we might want to work with the ItemTapped or ItemSelected events. You have a wide degree of flexibility here where you can choose to directly accept the EventArgs in your command or you can use a custom converter to grab the item from the EventArgs.

NavigationParameters

One of the breaking API changes you may notice is with the NavigationParameters. In the past, the NavigationParameters was based on a Dictionary which gave us the limitation that a key could only be used once in the querystring. While most of the time this was fine, there are so many cases where you just need to pass a list of something. Along with the new implementation are some great helpers including both a GetValue<T> and GetValues<T>. These are also safe to use if the key didn't actually exist so there's no more need for if( parameters.ContainsKey("foobar")) FooBar = (Foo)parameters["foobar"]. Naturally you will get a default value, so do check for `null`.

 

INavigationAware

Probably one of the most used interfaces in my Prism Forms apps, is INavigationAware. This is a major breaking change. That said, it's worth the frustration of the breaking change here. First of all INavigationAware is no longer a standalone interface. It is now actually the combination of two concepts INavigatingAware and INavigatedAware. As the verbs imply, one is based on Navigation that is about to occur, while the other is about Navigation that has occurred. One of the complaints I often heard, and frankly had myself was that with OnNavigatedTo, there was a visible UI update as my ViewModel was updating the Values that were bound on the UI. INavigatingAware with it's singular OnNavigatingTo really helps to address this problem.

 

The reason why we were seeing the UI changes was that the ViewModel never had a chance to load before we pushed the page onto the Navigation Stack. OnNavigatingTo is only called once, and only before we actually push the page to the stack. Like the sample below shows, we may have some default value that is really only there to alert the developer of a problem or is there for the design time. With the OnNavigatingTo, this value will no longer appear when the the page is actually pushed as the value of Message will update to whatever was in the NavigationParameters.
 
public class FooBarViewModel : BindableBase, INavigatingAware
{
	private INavigationService _navigationService { get; }

	public FooBarViewModel( INavigationService navigationService )
	{
		_navigationService = navigationService;
	}

	private string _message = "some default value"
	public string Message
	{
		get { return _message; }
		set { SetProperty( ref _message, value ); }
	}

	public void OnNavigatingTo( NavigationParameters parameters )
	{
		Message = parameters.GetValue<string>( "message" );
	}
}

BindableBase Update

So this one got snuck in last minute. BindableBase now allows you to specify an action when the value is changed. Also changed was the change up to call RaisePropertyChanged when a property has been changed. This becomes highly useful in a variety of situations like the with the following:
public class Person : BindableBase
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set { SetProperty( ref _firstName, value, () => RaisePropertyChanged( nameof( Name ) ) ); }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set { SetProperty( ref _lastName, value, () => RaisePropertyChanged( nameof( Name ) ) ); }
    }

    public string Name => $"{FirstName} {LastName}";
}

IActiveAware

For long time Prism users, IActiveAware is nothing new. In fact it's been there the whole time. But for Prism Forms, it's really been useless until 6.3.0. With the addition of behaviors, 6.3.0 adds a new behavior to help with one of the major problems that we have when using any MultiPage such as a TabbedPage or CarouselPage in our application. That problem of course, how on earth do you figure out when the user is actually on your page. How to handle the Children of a MultiPage is something that we will be seeing some additional work on before the next release. But in the mean time the IActiveAware behavior really gives us a great tool. Going forward with 6.3.0, I expect we will see a lot of developers adopting a pattern of making ViewModels for children of TabbedPages like the following:
public class TabbedChildPageAViewModel : BindableBase, INavigationAware, IActiveAware
{
	private bool isInitialized = false;

	public event EventHandler IsActiveChanged;

    private bool _isActive;
	public bool IsActive
    {
        get { return _isActive; }
        set { SetProperty( ref _isActive, value, OnIsActiveChanged ); }
    }

	public void OnNavigatingTo( NavigationParameters parameters )
	{
		if( isInitialized ) return;
		isInitialized = true;

		// Implement loading logic here
	}

    private void OnIsActiveChanged()
    {
        // Do Foo
    }
}
with a TabbedPage like the following:
public partial class MyTabbedPage : TabbedPage, INavigatingAware
{
	public MyTabbedPage()
    {
        InitializeComponent();
    }

    public void OnNavigatingTo( NavigationParameters parameters )
    {
        foreach( var child in Children )
        {
            // You only need to do this on the child if any of your child pages actually implement this.
            ( child as INavigatingAware )?.OnNavigatingTo( parameters );
            ( child?.BindingContext as INavigatingAware )?.OnNavigatingTo( parameters );
        }
    }
}
With this strategy you can now both initialize your Tabbed Page Children, and handle the Activation/Deactivation events that occur when the user changes the tab. You can check out a complete example of this in the Prism Samples.

Using Popup Pages with Prism for Xamarin Forms

So often as mobile developers we use some sort of Popup view. Really the reasons why we want to do this simple task are pretty endless. For too long it's been something that wasn't an option for Xamarin Forms. Then came one of my favorite new packages Rg.Plugins.Popup. The only problem is that the library requires navigation through their Popup Navigation Service instead of being integrated in with the Xamarin Forms.

This creates an issue for Prism Applications. How do you navigate to Popup Pages while maintaining a proper MVVM pattern? The solution, Prism.Plugin.Popups. With Prism.Plugin.Popups, Prism based apps can now navigate to Popup Pages using the Prism INavigationService that you're already using. Best of all, there is no configuration required. The plugin adds several new extensions in the Prism.Navigation namespace, so simply adding the INavigationService to your ViewModel and using the Prism.Navigation namespace is all you need to do.
 
using Prism.Navigation;
using Prism.Commands;
using Prism.Mvvm;

namespace MyApp.ViewModels
{
	public class MainPage : BindableBase
	{
		public MainPage( INavigationService navigationService )
		{
			_navigationService = navigationService;

			NavigateCommand = new DelegateCommand( OnNavigateCommandExecuted );
		}

		INavigationService _navigationService { get; }

		DelegateCommand NavigateCommand { get; }

		private async void OnNavigateCommandExecuted() =>
			_navigationService.PushPopupPageAsync( "MyPopupPage" );
	}
}
As mentioned before we're using the INavigationService, and just like the INavigationService you'll need to register your View and/or ViewModel the same as if you're registering any other pages for your application. One caveat to this, in order to function as an extension of the INavigationService it requires specific knowledge of the Container you're using as we have to use your container to resolve the View. As a result there is a container specific implementation for each of the public containers for Prism for Xamarin Forms.