backgroundTop
backgroundTop
Front Page
GreenBackgroundTop

Silverlight Prism

Prism for Silverlight - An Intro to Composite Applications

Prism can be thought of as a set of libraries that help Silverlight applications be scalable and testable. It has a number of features (modularity, view regions and commanding) that help with this. This guide shows you how to get started writing a Prism application in Silverlight. It shows how to use the bootstrappers, modules, catalogs, regions and commanding.

erikmork

17k Votes

GreenBackgroundBottom
 

Important Code

Mark as Inappropriate Content

This video is licensed under a Creative Commons License.

Creative Commons License Download the Video

Information From the Video

GreenBackgroundTop

Starting a Prism Application

Starting a Prism application is just like starting any other Silverlight application. File->New Silverlight Project. However, the Page.xaml (by convention) is often removed.
GreenBackgroundBottom
 
GreenBackgroundTop

Adding Shell.xaml

By convention, Prism applications have a Shell.xaml file. This control serves as a sort of Master Page for sub-views.
GreenBackgroundBottom
<UserControl x:Class="PrismSample.Shell"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:Regions="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation"
    Width="400" Height="300">
    <ItemsControl x:Name="MainRegion"
                  Regions:RegionManager.RegionName="MainRegion" />
</UserControl>
 
GreenBackgroundTop

Adding References to Prism

The Base project requires references to the Prism .dlls. Build and add refs to the following .dlls: Microsoft.Practices.Composite.dll, Microsoft.Practices.Composite.Presentation.dll, Microsoft.Practices.Composite.UnityExtensions.dll, Microsoft.Practices.ServiceLocation.dll, Microsoft.Practices.Unity.dll
GreenBackgroundBottom
 
GreenBackgroundTop

Adding Main Region

The Main Region is a kind of master page.
GreenBackgroundBottom
    <ItemsControl x:Name="MainRegion"
                  Regions:RegionManager.RegionName="MainRegion" />
 
GreenBackgroundTop

Adding the BootStrapper

The Bootstrapper is responsible for application initialization, registering of the main view and registering of the modules.
GreenBackgroundBottom
 public class Bootstrapper : UnityBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
            Shell shell = Container.Resolve<Shell>();
            Application.Current.RootVisual = shell;
            return shell;
        }

        protected override IModuleCatalog GetModuleCatalog()
        {
        }

    }
 
GreenBackgroundTop

Adding a Module

Modules are the units of separation in Prism. They mainly contain two things: 1) Services (classes that do things) and 2) Views (Controls that are displayed) To add a Module, simple add a .dll (or even .xap) to the solution. The Module typically requires references to the following .dlls: Microsoft.Practices.Composite.dll, Microsoft.Practices.Composite.Presentation.dll, Microsoft.Practices.Unity.dll
GreenBackgroundBottom
 
GreenBackgroundTop

Adding a View

Views are the user controls that are placed inside of Regions (the Master Page sort of things). To add a View, simply add a User Control.
GreenBackgroundBottom
 
GreenBackgroundTop

Simple ViewModel for MVVM

The ViewModel here is pretty simple. For display, it simply provides a list of companies. It also implements some commanding which we'll point out in just a moment.
GreenBackgroundBottom
public class ModuleAViewModel
    {


        public ModuleAViewModel()
        {
            Companies = new ObservableCollection<Company>();
            SignalSomething = new DelegateCommand<object>(
                executeCommand, canHandleButtonCommand);
        }

        public ObservableCollection<Company> Companies { get; set; }


        public ICompanyService CompanyService { get; set; }



        public DelegateCommand<object> SignalSomething
        {
            get;
            set;
        }

        public bool canHandleButtonCommand(object o)
        {
            return true;
        }

        public void executeCommand(object o)
        {
            if (CompanyService != null)
            {
                Companies.Clear();
                foreach (Company c in CompanyService.getCompanies())
                    Companies.Add(c);
            }
        }
    }
 
GreenBackgroundTop

Adding a Simple Service

Services are simple. They're basically just an interface. We'll add the implementation in a bit, but the point is that the ViewModel can ask the service (through the ICompanyService interface) to return a list of companies. This is a simplified, synchronous example. Typically, this service will need to support asynchronous requests.
GreenBackgroundBottom
    public class CompanyService : ICompanyService
    {

        #region ICompanyService Members

        public System.Collections.ObjectModel.ObservableCollection<Company> getCompanies()
        {
            return new Companies().List;
        }

        #endregion
    }
 
GreenBackgroundTop

XAML for the View

The view contains a couple of interesting features. Notice that the ViewModel is contained in the UserControl.Resources section. This approach often isn't the best (the view ultimately has to push services to the ViewModel), but it provides Blendability (the ability to see sample data in Blend). There's also a listbox bound to the Companies and a Button that fires commands back to the ViewModel.
GreenBackgroundBottom
<UserControl x:Class="ModuleA.Views.ModuleAView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:cal="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"
             xmlns:my="clr-namespace:ModuleA.Views"
             Width="400"
             Height="300">
    <UserControl.Resources>
        <my:ModuleAViewModel x:Key="theViewModel" />
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot"
          Background="White"
          DataContext="{Binding Path=., Source={StaticResource theViewModel}}"
          >
        <ListBox Width="150"
                 Height="200"
                 ItemsSource="{Binding Companies, Mode=TwoWay}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Content="SimpleButton"
                cal:Click.CommandParameter="SimpleButton"
                cal:Click.Command="{Binding SignalSomething}"
                HorizontalAlignment="Center"
                VerticalAlignment="Bottom" />

    </Grid>
</UserControl>
 
GreenBackgroundTop

Pushing Information to the ViewModel

In the View-first approach, the ViewModel is not constructed by Unity. This means that it doesn't have access to services from the rest of the application. In this case, it's necessary (though a bit ugly) to push information and possibly services to the ViewModel from the View (which is created by Unity).
GreenBackgroundBottom
        public ModuleAView(IUnityContainer container)
        {
            InitializeComponent();

            ModuleAViewModel vm = LayoutRoot.DataContext as ModuleAViewModel;
            vm.CompanyService = container.Resolve<ICompanyService>();
        }
 
GreenBackgroundTop

Adding the IModule type to the Module

Every Module requires an IModule type. This is the type that's responsible for initializing modules and registering a modules views and services.
GreenBackgroundBottom
    public class ModuleA : IModule
    {
        IRegionManager _regionManager;
        IUnityContainer _container;

        public ModuleA(IRegionManager regionManager, IUnityContainer container)
        {
            _regionManager = regionManager;
            _container = container;
        }

        #region IModule Members

        public void Initialize()
        {
            _container.RegisterType<ICompanyService, CompanyService>();
            _regionManager.RegisterViewWithRegion("MainRegion", typeof(ModuleAView));
            
        }

        #endregion
    }
 
GreenBackgroundTop

Registering a Module

Every Module must be registered. This allows Prism to load and use those modules. There are a number of ways to do this (through XAML, using strings or actual types). We're actually going to use a type because it's the easiest way.
GreenBackgroundBottom
        protected override IModuleCatalog GetModuleCatalog()
        {
            ModuleCatalog catalog = new ModuleCatalog();
            catalog.AddModule(typeof(ModuleA.ModuleA));
            return catalog;
        }
 
 
GreenBackgroundTop

References

Codeplex Site For Prism

This is the home of Prism. It will redirect to the MSDN code gallery to download Prism. Note: You do not need the project linker unless you're sharing code between WPF and Silverlight applications.

Interview with Prism Guys

Interview with Bob Brumfield and David Hill of Microsoft's Patterns and Practices team.

GreenBackgroundBottom
backgroundBottom
backgroundBottom