In addition to the typical bug fixes Prism 7.1 brings a much more consolidated approach to developing applications with Prism. Perhaps this is most apparent with Prism.Modularity now being defined entirely in the Prism.Core providing a consistent API for Prism.Forms and Prism.WPF, as well as making it available for the first time to Prism.Windows (in an upcoming preview).

Due to the major changes in where certain types are for Modularity (and Navigation for Prism.Forms), you may experience binary incompatibility issues when using libraries that target older versions of Prism.

Container Notices

Going forward we will only consider support for containers that work properly for Prism across all platforms.

Prism imposes the following requirements in order to use a container:

  • The container must be mutable to support Prism Modularity
  • The container must support Transient and Singleton registrations
  • The container must support registering a specified instance
  • The container must support keyed registrations / resolving by name
  • The container must support the WPF, UWP, and Xamarin.Forms platforms.

Autofac

This will be the final release with support for Autofac. Modularity is a core concept in Prism, which requires the use of a mutable container. The fact that the Autofac team has chosen to make Autofac immutable prevents us from being able to support the use of the Autofac container.

MEF

We will no longer be shipping or supporting MEF for WPF, nor will support be added for any other platforms.

Unity

Unity continues to be a very popular and fully supported container. For those upgrading to Prism 7.1 from Prism 6.X, note that you will need to uninstall the Unity references in your existing projects as the new maintainer for Unity has completely rearchitected the Unity Container. This included changing namespaces and changing how the library was shipped forcing the Prism team to change the NuGet that we target from Unity to Unity.Container.

IoC Alignment

Another big change we made to Prism was the introduction of a new Prism.IoC namespace that creates an abstraction around dependency injection containers.  Instead of using the container classes directly, you will now only use the IContainerRegistry and IContainerProvider interfaces provided by Prism.  The IContainerProvider  interface is used to resolve services from the container. The IContainerRegistry is used to register types with the container. Access to the actual DI container can be achieved by using the GetContainer() extension method off of the IContainerRegistry and IContainerProvider interfaces.  This greatly reduces the coupling of DI containers and your code base, and makes it much easier to not only maintain your apps, but to change DI containers by simply changing NuGet packages.  This also helps us align the Prism APIs more closely so that you have a ore consistent developer experience across platforms.

Navigation Alignment

With each release we move closer to a consolidated API across all supported platforms.  With the release of Prism 7.1, you will now find a new Prism.Navigation namespace that contains all the navigation interfaces in the Prism.Core NuGet package.  Currently, these interfaces are only compatible with Prism for Xamarin.Forms and Prism for Windows (UWP).  Therefore, if you are creating a WPF application, you will not see these interfaces in your API as they are excluded from the WPF platform target.  I plan on investigating how I can modify Prism for WPF to use these same interfaces and maintain backwards compatibility.

Module Alignment

Another API alignment we have made is Prism.Modularity.  The Prism.Modularity API is now shared across all WPF, Xamarin.Forms, and Windows (UWP).  In order to maintain backwards compatibility with WPF, some classes (such as the DirectoryModuleCatalog) and events are still only available in WPF.

Along with consolidating the Prism.Modularity API’s, we have introduced a breaking change in the definition of the IModule interface.  We have removed the Initialize() method and added two new methods.

“`cs
public interface IModule
{
void RegisterTypes(IContainerRegistry containerRegistry);
void OnInitialized(IContainerProvider containerProvider);
}
“`

You will need to update all your IModule implementations to no longer rely on the Initialize() method, and implement the new interface. This also means you will no longer be asking for your module dependencies in the ctor of your module class.  Now you will get them from the IContainerProvider.

Prism.WPF

The biggest change we have for Prism for WPF is a brand new PrismApplication base class.  The reason for this new application class is to create a consistent development API experience across all platforms, to reduce the amount of code to get started, and to have an easier and more intuitive API.  It is recommended that you use the new PrismApplication class going forward.  You will notice that the Bootstrapper class has been marked Obsolete.  However, the bootstrapper is not going to be removed ever!  We put the warning on the bootstrapper to help guide developers to the new PrismApplication class.  The PrismApplication class is where we will be focusing our efforts and aligning all the APIs across the supported platforms.  The Bootstrapper will remain for backwards compatibility and to support applications that do not necessarily run in an WPF application, such as a Visual Studio extension.

A feature worth noting here is the ability to opt-out of the NavigationJournal.  Sometimes when using region navigation, you may not want to have a particular view left on your navigation stack.  To opt-out of the navigation journal, simply have your View or ViewModel implement IJournalAware and set the PersistInHistory property to false.

Prism.Forms

As usual, Prism for Xamarin.Forms got the most attention when it comes to features.

Partial Views

The concept of a Partial View is to support a custom layout which may be reused across multiple pages, and eliminate ViewModel logic duplication by allowing that custom layout to rely on its own ViewModel. To use a Partial View you must set the ViewModelLocator.AutowirePartialView property with a reference to the containing page as shown here. You should not set the ViewModelLocator.AutowireViewModel property on the Partial View unless you are explicitly opting out as setting this property to true directly may result in the ViewModel being incorrectly set.

“`xml
<ContentPage xmlns=”http://xamarin.com/schemas/2014/forms”
xmlns:x=”http://schemas.microsoft.com/winfx/2009/xaml”
xmlns:local=”clr-namespace:AwesomeApp.Views”
xmlns:prism=”clr-namespace:Prism.Ioc;assembly=Prism.Forms”
xmlns:mvvm=”clr-namespace:Prism.Mvvm;assembly=Prism.Forms”
x:Name=”self”
x:Class=”AwesomeApp.Views.ViewA”>
<StackLayout>
<local:AwesomeView mvvm:ViewModelLocator.AutowirePartialView=”{x:Reference self}” />
<Entry Text=”{Binding SomeValue” />
</StackLayout>
</ContentPage>
“`

Dependency Resolver

Xamarin.Forms 3.1 introduces a new DependencyResolver. This enables applications using Dependency Injection to use their Container to resolve Platform Renderers and Effects which makes it possible to inject any services such as a logger. Since the default constructor was deprecated in Android Renderers as of Xamarin.Forms 2.5, Prism now includes a specific Android binary that enables the DependencyResolver to resolve types using

ContainerProvider

The Container Provider now allows types like ValueConverters to include Dependency Injection of Types/Services in the ctor, and allows the converter to be declared in XAML.

“`cs
namespace Contoso.Converters
{
public class MyValueConverter : IValueConverter
{
private ILoggerFacade _logger { get; }

public MyValueConverter(ILoggerFacade logger)
{
_logger = logger;
}

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
_logger.Log(“Converting value”, Category.Debug, Priority.None);
return value;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
_logger.Log(“Converting Value Back…”, Category.Debug, Priority.None);
return value;
}
}
}
“`

This can then be used in XAML using the ContainerProvider as follows:

“`xml
<ContentPage xmlns=”http://xamarin.com/schemas/2014/forms”
xmlns:x=”http://schemas.microsoft.com/winfx/2009/xaml”
xmlns:ioc=”clr-namespace:Prism.Ioc;assembly=Prism.Forms”
xmlns:converters=”using:Contoso.Converters”
x:Class=”Contoso.Views.ViewA”>
<ContentPage.Resources>
<ResourceDictionary>
<ioc:ContainerProvider x:TypeArguments=”converters:MyValueConverter” x:Key=”myValueConverter” />
</ResourceDictionary>
</ContentPage.Resources>
<Entry Text=”{Binding Demo,Converter={StaticResource myValueConverter}}” />
</ContentPage>
“`

Navigation Improvements

Previously, when using the relative back feature (“../” ) you would be required to provide a page that would be pushed onto the navigation stack. That is no longer required. You may now chain together any number of relative go-back instructions to “go back”.

For example:
Given your navigation stack looked like this: `NavigationPage/UserList/UserDetails/LoginPage/EditUser`

You can now indicate how many pages to remove, or “go back” by chaining the relative go-back instruction “../”.

`NavigationService.NavigateAsync(“../../../”);`

This would result in going back three pages leaving you with the following navigation stack:

`NavigationPage/UserList`

NOTE – The pages in the stack prior to the current page (last page in the nav stack) will be removed without calling any INavAware methods. Only the current page (EditUser in this example) would perform a proper GoBackAsync and execute the INavAware methods.

NOTE – This feature is only supported while within the context of a NavigationPage.

XAML Navigation

You can now use XAML Navigation Extensions to Navigate. This works well for scenarios where you may have a partial “MenuView” that may be reused across multiple Pages or where there may be no real reason to implement Navigation inside of a ViewModel.

“`xml
<!– basic nav –>
<Button Text=”Go To About” Command”{prism:NavigateTo ‘About’}” />

<!– basic nav without animation–>
<Button Text=”Go To About” Command”{prism:NavigateTo ‘About’, Animated=False}” />

<!– basic modal nav –>
<Button Text=”Go To About” Command”{prism:NavigateTo ‘About’, UseModalNavigation=True}” />

<!– custom can navigate support –>
<Button Text=”Go To About” Command=”{prism:NavigateTo ‘About’}” prism:Navigation.CanNavigate=”{Binding CanNavigate}” />

<!– go to new page, but remove one along the way –>
<Button Text=”Go To Settings” Command”{prism:NavigateTo ‘../Settings’}” />

<!– nav with VM Parameters –>
<Button Text=”Go To About”
Command”{prism:NavigateTo ‘About’}”
CommandParameters=”{Binding MyNavParams}” />

<!– Go Back –>
<Button Text=”Go Back” Command=”{prism:GoBack}” />

<!– Go Back To Root –>
<Button Text=”Go Back To Root” Command=”{prism:GoBack ToRoot}” />

<!– Xaml defined parameters –>
<Button Text=”Go To About” Command=”{prism:NavigateTo ‘About’}” >
<Button.CommandParameter>
<prism:XamlNavigationParameters Parent=”{x:Reference this}”>
<prism:XamlNavigationParameter Key=”MainPageViewModel” Value=”{Binding .}” />
</prism:XamlNavigationParameters>
</Button.CommandParameter>
</Button>

<!– can navigate on a parent object–>
<ContentView>
<ContentView prism:Navigation.CanNavigate=”False”>
<ContentView>
<Button Text=”Cannot Navigate” Command=”{prism:GoBack}” />
</ContentView>
</ContentView>
</ContentView>
“`

Prism.Windows

What about UWP? We have merged with Template 10 and are about to release a preview. This has been a very large effort spanning multiple teams and we are very excited to have this partnership with Template 10.  Expect a preview in the next couple of months.

Summary

Wow! That’s a lot of big changes!  I mean a freaking crap load of changes and features.  Hell, I didn’t even mention the other bug fixes and enhancements. For that, you should just go check out the release notes.

Thank you for being so patient with me over.  I know you have been waiting a long time for a lot of the new features, and most of you were using the previews or nightly builds in order to get them.

A big thank you to the community for all their time and effort helping us test and implement all these changes.

As always, big releases like this make me nervous.  Even with all the test coverage we have, there is always something that pops up that we didn’t foresee.  If you find any issues, please let us know over on the Prism Library GitHub site.  Now we have a ton of docs to write and even more samples to help everyone understand all these changes.

Feel free contact me on my blog, connect with me on Twitter (@brianlagunas), or leave a comment below for any questions or comments you may have.

Brian Lagunas

View all posts

3 comments

  • Hello Brian,

    Is there any way to resolve named dependency in a view model via constructor injection? I have the following 2 services registered
    containerRegistry.Register(“Local”);;
    containerRegistry.Register();

    I need to be able to access them as needed seperately. I have been able to do that by injecting IContainerProvider and resolving it from that in view model. However, I read in one of your other blogs that it is not recommended. Do you have any suggestions how to do this?
    Best,
    Grant

Follow Me

Follow me on Twitter, subscribe to my YouTube channel, and watch me stream live on Twitch.