Prism Framework for Universal Windows Platform

In this article, I will explain how to implement Prism framework for UWP apps and advantages of using Prism framework.

Let me begin with the advantages of using Prism framework.

  • It helps to make it easier to achieve MVVM, Dependency Injection, Commanding, Event Aggregation, Backbutton Handling and more.

  • It helps to write well structured and maintainable XAML applications.

  • It contains code that you don't need to write yourself anymore. One example is the ViewModel data saving to local storage when navigating.

Create new Universal Windows project, I have named it as MyPrismApp.



Install the below packages using Package Manager Console.



App.xaml.cs

Remove the class "Application" which was inherited by the class "App" and replace with the class "PrismUnityApplication".

(For those who used prism library in Universal windows 8.1- we are not inheriting with MvvmAppBase any more).

Remove OnLaunched method and add the below code.

  1. protected override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)    
  2. {    
  3.     NavigationService.Navigate("Main"null);    
  4.   
  5.     Window.Current.Activate();    
  6.   
  7.     return Task.FromResult<object>(null);    
  8. }    
  9.   
  10. protected override Task OnInitializeAsync(IActivatedEventArgs args)    
  11. {    
  12.     RegisterTypes();    
  13.     return base.OnInitializeAsync(args);    
  14. }    
  15.   
  16. private void RegisterTypes()    
  17. {    
  18.     ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>    
  19.     {    
  20.         var viewModelTypeName = string.Format(System.Globalization.CultureInfo.InvariantCulture, "MyPrismApp.ViewModels.{0}ViewModel, MyPrismApp", viewType.Name);    
  21.         var viewModelType = Type.GetType(viewModelTypeName);    
  22.         return viewModelType;    
  23.     });    
  24. }    

The ViewModelLocationProvider code tells Prism where to look for ViewModels file with naming convention.

Your App.xaml.cs page looks like below,

  1. using Prism.Unity.Windows;    
  2. using System;    
  3. using System.Collections.Generic;    
  4. using System.IO;    
  5. using System.Linq;    
  6. using System.Runtime.InteropServices.WindowsRuntime;    
  7. using Prism.Mvvm;    
  8. using System.Threading.Tasks;    
  9. using Windows.ApplicationModel;    
  10. using Windows.ApplicationModel.Activation;    
  11. using Windows.Foundation;    
  12. using Windows.Foundation.Collections;    
  13. using Windows.UI.Xaml;    
  14. using Windows.UI.Xaml.Controls;    
  15. using Windows.UI.Xaml.Controls.Primitives;    
  16. using Windows.UI.Xaml.Data;    
  17. using Windows.UI.Xaml.Input;    
  18. using Windows.UI.Xaml.Media;    
  19. using Windows.UI.Xaml.Navigation;      
  20.     
  21. namespace MyPrismApp    
  22. {    
  23.     /// <summary>    
  24.     /// Provides application-specific behavior to supplement the default Application class.    
  25.     /// </summary>    
  26.     sealed partial class App : PrismUnityApplication    
  27.     {    
  28.         /// <summary>    
  29.         /// Initializes the singleton application object.  This is the first line of authored code    
  30.         /// executed, and as such is the logical equivalent of main() or WinMain().    
  31.         /// </summary>    
  32.         public App()    
  33.         {    
  34.             this.InitializeComponent();    
  35.             this.Suspending += OnSuspending;    
  36.         }    
  37.     
  38.         protected override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)    
  39.         {    
  40.             NavigationService.Navigate("Main"null);    
  41.     
  42.             Window.Current.Activate();    
  43.     
  44.             return Task.FromResult<object>(null);    
  45.         }    
  46.     
  47.         protected override Task OnInitializeAsync(IActivatedEventArgs args)    
  48.         {    
  49.             RegisterTypes();    
  50.             return base.OnInitializeAsync(args);    
  51.         }    
  52.     
  53.         private void RegisterTypes()    
  54.         {    
  55.             ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>    
  56.             {    
  57.                 var viewModelTypeName = string.Format(System.Globalization.CultureInfo.InvariantCulture, "MyPrismApp.ViewModels.{0}ViewModel, MyPrismApp", viewType.Name);    
  58.                 var viewModelType = Type.GetType(viewModelTypeName);    
  59.                 return viewModelType;    
  60.             });    
  61.         }    
  62.             
  63.         /// <summary>    
  64.         /// Invoked when Navigation to a certain page fails    
  65.         /// </summary>    
  66.         /// <param name="sender">The Frame which failed navigation</param>    
  67.         /// <param name="e">Details about the navigation failure</param>    
  68.         void OnNavigationFailed(object sender, NavigationFailedEventArgs e)    
  69.         {    
  70.             throw new Exception("Failed to load Page " + e.SourcePageType.FullName);    
  71.         }    
  72.     
  73.         /// <summary>    
  74.         /// Invoked when application execution is being suspended.  Application state is saved    
  75.         /// without knowing whether the application will be terminated or resumed with the contents    
  76.         /// of memory still intact.    
  77.         /// </summary>    
  78.         /// <param name="sender">The source of the suspend request.</param>    
  79.         /// <param name="e">Details about the suspend request.</param>    
  80.         private void OnSuspending(object sender, SuspendingEventArgs e)    
  81.         {    
  82.             var deferral = e.SuspendingOperation.GetDeferral();    
  83.             //TODO: Save application state and stop any background activity    
  84.             deferral.Complete();    
  85.         }    
  86.     }    
  87.  

App.xaml

Add the namespace "xmlns:prism="using:Prism.Unity.Windows"" and replace Application with "prism:PrismUnityApplication".

  1. <prism:PrismUnityApplication    
  2.     x:Class="MyPrismApp.App"    
  3.     xmlns:prism="using:Prism.Unity.Windows"    
  4.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
  5.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
  6.     xmlns:local="using:MyPrismApp"    
  7.     RequestedTheme="Light">    
  8.     
  9. </prism:PrismUnityApplication>  
Now we are done with App page. 

Next we need to delete MainPage and create three folders "Views", "Models", "ViewModels" and create a page under the Views folder and name it as MainPage.

MainPage.xaml

Add the namespace "xmlns:prism="using:Prism.Windows.Mvvm"" and replace "page" with "prism:SessionStateAwarePage" and add "prism:ViewModelLocator.AutoWireViewModel="True""

  1. <prism:SessionStateAwarePage    
  2.     x:Class="MyPrismApp.Views.MainPage"    
  3.     xmlns:prism="using:Prism.Windows.Mvvm"     
  4.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
  5.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
  6.     xmlns:local="using:MyPrismApp.Views"    
  7.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    
  8.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    
  9.     prism:ViewModelLocator.AutoWireViewModel="True"       
  10.     mc:Ignorable="d">    
  11.     
  12.     <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">    
  13.         <StackPanel>    
  14.             <TextBlock Text="{Binding Title}" FontSize="{StaticResource TextStyleExtraLargeFontSize}" Margin="15"/>    
  15.             <ListView Margin="15" ItemsSource="{Binding Countries}">    
  16.                 <ListView.ItemTemplate>    
  17.                     <DataTemplate>    
  18.                         <Grid>    
  19.                             <Grid.ColumnDefinitions>    
  20.                                 <ColumnDefinition Width="100"/>    
  21.                                 <ColumnDefinition Width="*"/>    
  22.                             </Grid.ColumnDefinitions>    
  23.                             <TextBlock Text="{Binding CountryCode}"/>    
  24.                             <TextBlock Text="{Binding CountryName}" Grid.Column="1"/>    
  25.                         </Grid>    
  26.                     </DataTemplate>    
  27.                 </ListView.ItemTemplate>    
  28.             </ListView>    
  29.         </StackPanel>    
  30.     </Grid>    
  31.     
  32. </prism:SessionStateAwarePage>   

MainPage.xaml.cs

Remove the class "Page" which was inherited by the class "MainPage" and replace with the class :SessionStateAwarePage".

(For those who used prism library in Universal windows 8.1- we are not inheriting with VisualStateAwarePage any more).

  1. using Prism.Windows.Mvvm;   
  1. namespace MyPrismApp.Views    
  2. {    
  3.        
  4.     public sealed partial class MainPage : SessionStateAwarePage    
  5.     {    
  6.         public MainPage()    
  7.         {    
  8.             this.InitializeComponent();    
  9.         }    
  10.     }    
  11. }     

Model Class

Add a class file in Models folder and name it as Country.

  1. namespace MyPrismApp.Models    
  2. {    
  3.     public class Country    
  4.     {    
  5.         private string countryCode;    
  6.         private string countryName;    
  7.     
  8.         public string CountryCode    
  9.         {    
  10.             get { return countryCode; }    
  11.             set { countryCode = value; }    
  12.         }    
  13.          
  14.         public string CountryName    
  15.         {    
  16.             get { return countryName; }    
  17.             set { countryName = value; }    
  18.         }    
  19.     
  20.     }    
  21. }  
ViewModel Class

Add a class in ViewModels folder and name it as MainPageViewModel (Should use the same name of your view followed by ViewModel.)

Inherit your ViewModel class with ViewModelBase.
  1. using Prism.Windows.Mvvm;    
  2. using System;    
  3. using System.Collections.Generic;    
  4. using System.Linq;    
  5. using System.Text;    
  6. using System.Threading.Tasks;    
  7. using Prism.Windows.Navigation;    
  8. using System.Collections.ObjectModel;    
  9. using MyPrismApp.Models;    
  10.     
  11. namespace MyPrismApp.ViewModels    
  12. {    
  13.     public class MainPageViewModel : ViewModelBase    
  14.     {            
  15.         private string title = "Countries with code";    
  16.     
  17.         public string Title    
  18.         {    
  19.             get { return title; }    
  20.             set { title = value; }    
  21.         }    
  22.     
  23.     
  24.         private ObservableCollection<Country> countries;    
  25.     
  26.         public ObservableCollection<Country> Countries    
  27.         {    
  28.             get { return countries; }    
  29.             set { countries = value; }    
  30.         }    
  31.     
  32.     
  33.         public override void OnNavigatedTo(NavigatedToEventArgs e, Dictionary<stringobject> viewModelState)    
  34.         {    
  35.             base.OnNavigatedTo(e, viewModelState);    
  36.     
  37.             Countries = new ObservableCollection<Country>();    
  38.     
  39.             Countries.Add(new Country() { CountryCode = "1", CountryName = "Canada" });    
  40.             Countries.Add(new Country() { CountryCode = "1", CountryName = "United States" });    
  41.             Countries.Add(new Country() { CountryCode = "44", CountryName = "United Kingdom" });    
  42.             Countries.Add(new Country() { CountryCode = "91", CountryName = "India" });    
  43.         }    
  44.     }    
  45. }   
Now we are good to go, hit run button.



Prism has one more important advantage called "Design Time", we can bind the data and display it in screen before running it, which really helps for design alignment and saves lot of time -- cool isn't it?

DesignTime

Create a folder "DesignTime" and add a class and name it as "MainPageDesignTimeViewModel" and paste the below code.
  1. using MyPrismApp.Models;    
  2. using System;    
  3. using System.Collections.Generic;    
  4. using System.Collections.ObjectModel;    
  5. using System.Linq;    
  6. using System.Text;    
  7. using System.Threading.Tasks;    
  8.     
  9. namespace MyPrismApp.DesignTime    
  10. {    
  11.     public class MainPageDesignTimeViewModel    
  12.     {    
  13.         public MainPageDesignTimeViewModel()    
  14.         {    
  15.             Title = "Countries with code";    
  16.     
  17.             Countries = new ObservableCollection<Country>();    
  18.     
  19.             Countries.Add(new Country() { CountryCode = "1", CountryName = "Canada" });    
  20.             Countries.Add(new Country() { CountryCode = "1", CountryName = "United States" });    
  21.             Countries.Add(new Country() { CountryCode = "44", CountryName = "United Kingdom" });    
  22.             Countries.Add(new Country() { CountryCode = "91", CountryName = "India" });    
  23.         }    
  24.     
  25.         private string title;    
  26.     
  27.         public string Title    
  28.         {    
  29.             get { return title; }    
  30.             set { title = value; }    
  31.         }    
  32.     
  33.         private ObservableCollection<Country> countries;    
  34.     
  35.         public ObservableCollection<Country> Countries    
  36.         {    
  37.             get { return countries; }    
  38.             set { countries = value; }    
  39.         }    
  40.     }    
  41. }   
MainPage.xaml

Add the namespace "xmlns:designTime="using:MyPrismApp.DesignTime"" and set the data context of designtime viewmodel.
  1. <d:prism.DataContext>   
  2.    <designTime:MainPageDesignTimeViewModel/>   
  3. </d:prism.DataContext>   
Build the app once and see the design page where you can see the list of data binded to listview.



Source code ha been included, if you have any queries feel free to ask.