Creating WPF programs using Prism and MVVM architecture

How to use Prism library and MVVM architecture pattern to develop WPF applications. No matter how large or complex your application is, this foundation is the same for all types of projects. That's why it's important to understand its behavior. We will learn how to use UnityContainer and how to use Prism to achieve modularity in WPF applications.

Prism is a framework for building loosely coupled, maintainable and testable XAML applications in WPF.

Note: the project download is attached for your reference. The source code is free to use and developed for learning purposes only.

Start visual studio and click createWPFAPP(.NetFramework): name your application as needed. As this is a demonstration project, I chose My_First_WPF_App

Right click your project (not a solution) and add a new window to your My_First_WPF_App project. Name your window Shell xaml. The Shell is your main layout: it will load areas for your WPF application. You can delete MainWindow Xaml or rename to Shell xaml

Let's start with Prism installation: use Nuget package manager to install Prism Add unity to your shell project. Right click the project and click Nuget package manager (see figure below). Then click Install. This will install the Prism library into your project.

Prism. After the installation of unity is successful. Expand the reference of the project to check whether the prism library has been added.

  1. Now we have an entry point - shell Xaml, we will load our module from there. We need a class to load the shell. To do this, we will add the class to my_ First_ WPF_ In the app project and name it BootStrapper.
     
  2. Note: set the BootStrapper class to Public and inherit from the unitybootstamper class,
    Unitybootsupper class from namespace: use prism Unity;
using System;      
using System.Windows;      
using Prism.Unity;      
      
namespace My_First_WPF_App      
{      
    /// <summary>      
    /// BootStrapper is responsible for loading prism and initializing Shell.      
    /// </summary>      
    [Obsolete]      
    public class BootStrapper : UnityBootstrapper      
    {      
        #region Overridden Methods      
        /// <summary>      
        /// Entry point to the application      
        /// </summary>      
        /// <param name="runWithDefaultConfiguration"></param>      
        public override void Run(bool runWithDefaultConfiguration)      
        {      
            base.Run(runWithDefaultConfiguration);      
        }      
      
        /// <summary>      
        /// Initializes shell.xaml      
        /// </summary>      
        /// <returns></returns>      
        protected override DependencyObject CreateShell()      
        {      
            return Container.TryResolve<Shell>();      
        }      
      
        /// <summary>      
        /// loads the Shell.xaml      
        /// </summary>      
        protected override void InitializeShell()      
        {      
            App.Current.MainWindow = (Window)Shell;      
            App.Current.MainWindow.Show();      
        }      
      
        /// <summary>      
        /// Add view(module) from other assemblies and begins with modularity      
        /// </summary>      
        protected override void ConfigureModuleCatalog()      
        {      
            base.ConfigureModuleCatalog();      
        }      
        #endregion      
    }      
}      

using System.Windows;      
      
namespace My_First_WPF_App      
{      
    /// <summary>      
    /// Interaction logic for App.xaml      
    /// </summary>      
    public partial class App : Application      
    {      
        protected override void OnStartup(StartupEventArgs e)      
        {      
            base.OnStartup(e);      
            BootStrapper bootStrapper = new BootStrapper();      
            bootStrapper.Run();      
        }      
    }      
} 
  1. Run your project and see its magic. Your project will be loaded into the Shell window, and now we have Shell as the entry point.
     
  2. Now we have control of shell Xaml, it's time to add some modularity to your project.
    1. Go to shell xaml
    2. First, add the Prism namespace: xmlns:prism=“ http://prismlibrary.com/"
    3. Create ItemsControl in your grid: < ItemsControl prism: regionmanager RegionName="Shell"/>
<Window x:Class="My_First_WPF_App.Shell"      
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"      
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"      
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"      
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"      
        mc:Ignorable="d"      
        xmlns:prism="http://prismlibrary.com/"      
        Title="Shell" Height="450" Width="800">      
    <Grid>      
        <ItemsControl prism:RegionManager.RegionName="Shell"/>      
    </Grid>      
</Window>  

Now that we have set up our main project, it's time to add some modules. Because the 3-tier architecture has {3 basic modules. This is a demo project, so we will only create one demo module, the class library (DLL). Right click the solution and add the DLL to your solution file. Name your DLL presentation.

Let's create the View and ViewModels folders in this DLL. (in the same way, right-click the presentation, add a new folder from the submenu, and rename it View. The same is true for ViewModel)

    • Put our first UserControl Add XAML to the View folder and name it welcome pageview Xaml(WPF).
    • In the same way, we add the C# class file to the ViewModel folder and name it welcomepageviewmodel cs
  1. Add Prism to the newly created presentation DLL.
  2. Open WelcomePageView: add namespace and set AutoWireViewModel to true in UserControl tag
    (see the bold section of the code snippet below.)
<UserControl x:Class="Presentation.View.WelcomePageView"      
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"                  
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"      
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"      
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"      
             xmlns:prism="http://prismlibrary.com/"    
             prism:ViewModelLocator.AutoWireViewModel="True"    
             mc:Ignorable="d"                 
             d:DesignHeight="450" d:DesignWidth="800"> 
  1. Now we need the module locator, so in the presentation DLL project and name it modulelocators cs
    1. Use prism Modularity inherits classes from the Imodule interface;
    2. Implementation interface
    3. Create an instance of IRegionManager
    4. Create a parameterized constructor and assign it to the instance
    5. By overriding the OnInitialized method, you can now leave RegisterTypes blank.
using Prism.Ioc;        
using Prism.Modularity;        
using Prism.Regions;        
        
namespace Presentation        
{        
    /// <summary>        
    /// Responsible for mapping modules        
    /// </summary>        
    public class ModuleLocators : IModule        
    {        
        #region private properties        
        /// <summary>        
        /// Instance of IRegionManager        
        /// </summary>        
        private IRegionManager _regionManager;        
     
        #endregion        
     
        #region Constructor        
        /// <summary>        
        /// parameterized constructor initializes IRegionManager        
        /// </summary>        
        /// <param name="regionManager"></param>        
        public ModuleLocators(IRegionManager regionManager)        
        {        
            _regionManager = regionManager;        
        }        
        #endregion        
     
        #region Interface methods        
        /// <summary>        
        /// Initializes Welcome page of your application.        
        /// </summary>        
        /// <param name="containerProvider"></param>        
        public void OnInitialized(IContainerProvider containerProvider)        
        {        
            _regionManager.RegisterViewWithRegion("Shell", typeof(ModuleLocators));  //ModuleLocators is added for testing purpose,     
//later we'll replace it with WelcomePageView      
        }        
        
        /// <summary>        
        /// RegisterTypes used to register modules        
        /// </summary>        
        /// <param name="containerRegistry"></param>        
        public void RegisterTypes(IContainerRegistry containerRegistry)        
        {        
        }        
        #endregion        
    }        
}     

Let's add a reference to the demo module to the (My_First_WPF_App) project. Right click my_ First_ WPF_ App and click Add Reference, then go to the project and select Presentation. Click OK.

Now it's time to tell BootStrapper which module it should look for. Open BootStrapper CS, in the ConfigureModuleCatalog.

using System;      
using System.Windows;      
using Prism.Unity;      
      
namespace My_First_WPF_App      
{      
    /// <summary>      
    /// BootStrapper is responsible for loading prism and initializing Shell.      
    /// </summary>      
    [Obsolete]      
    public class BootStrapper : UnityBootstrapper      
    {      
        #region Overridden Methods      
        /// <summary>      
        /// Entry point to the application      
        /// </summary>      
        /// <param name="runWithDefaultConfiguration"></param>      
        public override void Run(bool runWithDefaultConfiguration)      
        {      
            base.Run(runWithDefaultConfiguration);      
        }      
      
        /// <summary>      
        /// Initializes shell.xaml      
        /// </summary>      
        /// <returns></returns>      
        protected override DependencyObject CreateShell()      
        {      
            return Container.TryResolve<Shell>();      
        }      
      
        /// <summary>      
        /// loads the Shell.xaml      
        /// </summary>      
        protected override void InitializeShell()      
        {      
            App.Current.MainWindow = (Window)Shell;      
            App.Current.MainWindow.Show();      
        }      
      
        /// <summary>      
        /// Add view(module) from other assemblies and begins with modularity      
        /// </summary>      
        protected override void ConfigureModuleCatalog()      
        {      
            base.ConfigureModuleCatalog();      
            Type ModuleLocatorType = typeof(Presentation.ModuleLocators);      
            ModuleCatalog.AddModule(new Prism.Modularity.ModuleInfo      
            {      
                ModuleName = ModuleLocatorType.Name,      
                ModuleType = ModuleLocatorType.AssemblyQualifiedName      
            });      
        }      
        #endregion      
    }      
}    

Now go to the ModuleLocators class of the Presentation module. In the internal method OnInitialized(), change the type from NewlyCreatedView to welcome pageview.

using Prism.Ioc;      
using Prism.Modularity;      
using Prism.Regions;      
      
namespace Presentation      
{      
    /// <summary>      
    /// Responsible for mapping modules      
    /// </summary>      
    public class ModuleLocators : IModule      
    {      
        #region properties      
        /// <summary>      
        /// Instance of IRegionManager      
        /// </summary>      
        private IRegionManager _regionManager;      
   
        #endregion      
   
        #region Constructor      
        /// <summary>      
        /// parameterized constructor initializes IRegionManager      
        /// </summary>      
        /// <param name="regionManager"></param>      
        public ModuleLocators(IRegionManager regionManager)      
        {      
            _regionManager = regionManager;      
        }      
        #endregion      
   
        #region Interface methods      
        /// <summary>      
        /// Initializes Welcome page of your application.      
        /// </summary>      
        /// <param name="containerProvider"></param>      
        public void OnInitialized(IContainerProvider containerProvider)      
        {      
            _regionManager.RegisterViewWithRegion("Shell", typeof(View.WelcomePageView));      
        }      
      
        /// <summary>      
        /// RegisterTypes used to register modules      
        /// </summary>      
        /// <param name="containerRegistry"></param>      
        public void RegisterTypes(IContainerRegistry containerRegistry)      
        {      
        }      
        #endregion      
    }      
}  

Add a Textblock in the welcome page view to see if it works properly.

<UserControl x:Class="Presentation.View.WelcomePageView"      
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"      
             xmlns:prism="http://prismlibrary.com/"      
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"      
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"      
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"      
             mc:Ignorable="d"      
             prism:ViewModelLocator.AutoWireViewModel="True"      
             d:DesignHeight="450" d:DesignWidth="800">      
    <Grid>      
    <TextBlock Text="You successfully have configured Prism into your APP" />      
    </Grid>      
</UserControl> 

We have added Prism to our project and we have finally achieved modularity. The final step is to have the view communicate with the view model using the MVVM pattern. We will do this through DataContext.

Let's add another text block in the welcome pageview and bind it using the string attribute in the welcome pageviewmodel.

<UserControl x:Class="Presentation.View.WelcomePageView"      
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"      
             xmlns:prism="http://prismlibrary.com/"      
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"      
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"      
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"      
             mc:Ignorable="d"      
             prism:ViewModelLocator.AutoWireViewModel="True"      
             d:DesignHeight="450" d:DesignWidth="800">      
    <Grid>      
        <Grid.RowDefinitions>      
            <RowDefinition/>      
            <RowDefinition/>      
        </Grid.RowDefinitions>      
        <TextBlock Text="You successfully have configured Prism into your APP" />      
        <TextBlock Text="{Binding ImGoodByeText}" Grid.Row="1"/>      
    </Grid>      
</UserControl>    

using System;      
      
namespace Presentation.ViewModel      
{      
    /// <summary>      
    /// View Model of WelcomePage, responsible for logic for respected view.      
    /// </summary>      
   public class WelcomePageViewModel      
    {      
        #region Properties      
            /// <summary>      
            /// This string property will have default text for demo purpose.    
            /// </summary>      
            private string _imGoodByeText = "This is binded from WelcomePageViewModel, Thank you for being part of this Blog!";      
            /// <summary>      
            /// This string property will be binded with Textblock on view       
            /// </summary>      
            public string ImGoodByeText      
            {      
                get { return _imGoodByeText; }      
                set { _imGoodByeText = value; }      
            }      
        #endregion      
      
    }      
}   

using Presentation.ViewModel;      
using System.Windows.Controls;      
      
namespace Presentation.View      
{      
    /// <summary>      
    /// Interaction logic for WelcomePageView.xaml      
    /// </summary>      
    public partial class WelcomePageView : UserControl      
    {      
        public WelcomePageView()      
        {      
            InitializeComponent();      
            this.DataContext = new WelcomePageViewModel();      
        }      
    }      
}   

Tags: C# WPF mvvm programming language

Posted by ukspudnie on Fri, 13 May 2022 03:57:49 +0300