Partager via


Composite Application Guidance for WPF Hands-On Lab

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Purpose

In this lab, you will learn the basic concepts of the Composite Application Guidance for WPF (Windows Presentation Foundation) and apply them to create a Composite Application Library solution that you can use as the starting point for building a composite WPF application. After completing this lab, you will be able to do the following:

  • You will understand the basic concepts of the Composite Application Guidance for WPF.
  • You will create a new solution based on the Composite Application Library.
  • You will create a module and load it statically.
  • You will create a view and show it in the Shell window.

Preparation

This topic requires you to have the following Composite Application Library and Unity Application Block assemblies:

  • Microsoft.Practices.Composite.dll
  • Microsoft.Practices.Composite.Wpf.dll
  • Microsoft.Practices.Composite.UnityExtensions.dll
  • Microsoft.Practices.Unity.dll
  • Microsoft.Practices.ObjectBuilder2.dll

The Composite Application Library ships as source code, which means you must compile it to get the Composite Application Library assemblies (Microsoft.Practices.Composite.dll, Microsoft.Practices.Composite.Wpf.dll, and Microsoft.Practices.Composite.UnityExtensions.dll).

To compile the solution

  1. In Windows Explorer, double-click the following batch file to open the Composite Application Library solution in Visual Studio:

    Open Composite Application Library Solution.bat

  2. Build the solution. The Composite Application Library assemblies will be placed at the CAL\Composite.UnityExtensions\bin\Debug folder.

Procedures

This lab includes the following tasks:

  • Task 1: Understanding the Composite Application Guidance for WPF
  • Task 2: Creating a Solution Using the Composite Application Library
  • Task 3: Adding a Module
  • Task 4: Adding a View

The next sections describe each of these tasks.

Note

The instructions of this hands-on lab are based on the HelloWorld solution. To open the solution in Visual Studio, run the Open Hello World Solution.bat file.

Task 1: Understanding the Composite Application Guidance for WPF

The Composite Application Guidance for WPF is a set of guidance for developing complex WPF applications. The complexity this refers to occurs when there are multiple independently evolving pieces in an application that need to work together. The Composite Application Guidance is designed to help you manage this complexity. It includes a reference implementation, reusable library code (named Composite Application Library), and pattern guidance.

Background: Composite Applications

A composite application is composed of a number of discrete and independent components. To the user, the application appears as a seamless program that offers many capabilities. These components are integrated together in a host environment to form a coherent solution. Figure 1 shows an example of a composite application.

Ff921141.a4775e72-7ce8-4119-95e1-38f4065cc395(en-us,PandP.10).png

Figure 1
Composite application

The Composite Application Guidance for WPF targets composite applications built with WPF.

Background: Containers

Applications built using the Composite Application Library are composites that potentially consist of many loosely coupled components that need a way to interact and communicate with one another to deliver the required business functionality.

To tie together these various modules, applications built using the Composite Application Library rely on a dependency injection container. The container offers a collection of services. A service is an object that provides functionality to other components in a loosely coupled way through an interface and is often a singleton. The container creates instances of components that have service dependencies. During the component's creation, the container injects any dependencies that the component has requested into it. If those dependencies have not yet been created, the container creates and injects them first.

There are several advantages of using a container:

  • A container removes the need for a component to have to locate its dependencies or manage their lifetimes.
  • A container allows swapping the implementation of the dependencies without affecting the component.
  • A container facilitates testability by allowing dependencies to be mocked.
  • A container increases maintainability by allowing new services to be easily added to the system.

For more information about containers, see Container design concept.

Task 2: Creating a Solution Using the Composite Application Library

In this task, you will create a solution using the Composite Application Library. You will be able to use this solution as a starting point for your composite Windows Presentation Foundation (WPF) application. The solution includes recommended practices and techniques and is the basis for the procedures in the Composite Application Guidance for WPF. To create a solution with the Composite Application Library, the following tasks must be performed:

  1. Create a solution with a Shell project. In this task, you create the initial Visual Studio solution and add a WPF Application project that is the basis of solutions built using Composite Application Library. This project is known as the Shell project.
  2. Set up the Shell window. In this task, you set up a window—the Shell window—to host different user interface (UI) components in a decoupled way.
  3. Set up the application's bootstrapper. In this task, you set up code that initializes the application.

The following procedure describes how to create a solution with a Shell project. A Shell project is the basis of a typical application built using the Composite Application Library—it is a WPF Application project that contains the application's startup code, known as the bootstrapper, and a main window where views are typically displayed (the Shell window).

To create a solution with a Shell project

  1. In Visual Studio, create a new WPF application. To do this, point to New on the File menu, and then click Project. In the Project types list, select **Windows **inside the Visual C# node. In the Templates box, click WPF Application. Finally, set the project's name to HelloWorld, specify a valid location, and then click OK.

    Visual Studio will create the HelloWorld project, as illustrated in Figure 2. This project will be the Shell project of your application.

    Ff921141.33081762-b628-4d2b-8742-aafce2e0060e(en-us,PandP.10).png

    Figure 2
    HelloWorld project

  2. Using Windows Explorer, create a folder named Library inside your solution's folder and copy the following assemblies into it:

    • Microsoft.Practices.Composite.dll. This assembly contains the implementation of the Composite Application Library core components such as modularity, logging services, communication services, and definitions for several core interfaces. This assembly does not contain UI-specific elements.
    • Microsoft.Practices.Composite.Wpf.dll. This assembly contains the implementation of Composite Application Library components that target WPF applications, including commands, regions, and events.
    • Microsoft.Practices.Composite.UnityExtensions.dll. This assembly contains base and utility classes you can reuse in applications built with the Composite Application Library that consume the Unity Application Block. For example, it contains a bootstrapper base class—the UnityBootstrapper class—that creates and configures a Unity container with default Composite Application Library services when the application starts.
    • Microsoft.Practices.Unity.dll and Microsoft.Practices.ObjectBuilder2.dll. These assemblies enable you to use the Unity Application Block in your application. By default, applications built using the Composite Application Guidance for WPF use the Unity Application Block. However, developers who prefer to use different container implementations can build adapters for them using the provided extensibility points in the Composite Application Library.
  3. In the HelloWorld project, add references to the assemblies mentioned in the previous step. To do this, right-click the HelloWorld project in Solution Explorer, click Add Reference, click Browse in the Add Reference dialog box, browse to and select the assemblies you want to add, and then click OK.

The Shell window is the top-level window of an application based on the Composite Application Library. This window is a place to host different user interface (UI) components that exposes a way for itself to be dynamically populated by others, and it may also contain common UI elements, such as menus and toolbars. The Shell window sets the overall look and feel of the application.

The following procedure explains how to set up the Shell window.

To set up the Shell window

  1. In Solution Explorer, rename the file Window1.xaml to Shell.xaml.

  2. Open the code behind file Shell.xaml.cs and rename the Window1 class to Shell using the Visual Studio refactoring tools. To do this, right-click Window1 in the class signature, point to Refactor, and then click Rename, as illustrated in Figure 3. In the Rename dialog box, type Shell as the new name, and then click OK. If the Preview Changes – Rename dialog box appears, click Apply.

    Ff921141.b5747039-ebd5-4b19-86d1-146b2eb18494(en-us,PandP.10).png

    Figure 3
    Window1 renaming using Visual Studio refactoring tools

  3. In XAML view, open the Shell.xaml file, and then set the following attribute values to the **Window **root element:

    • x:Class = "HelloWorld.Shell" (this matches the code behind class's name)
    • Title = "Hello World"

    Your code should look like the following.

    <Window x:Class="HelloWorld.Shell"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        Title="Hello World" Height="300" Width="300">
        <Grid>
    
        </Grid>
    </Window>
    

Regions

Conceptually, a region is a mechanism that developers can use to expose to the application's WPF container controls—those that permit child elements—as components that encapsulate a particular visual way of displaying views (typically, views are user controls). Regions can be accessed in a decoupled way by their name and support adding or removing views dynamically at run time.

By showing controls through regions, you can consistently display and hide the views, independently of the visual style in which they display. This allows the appearance, behavior, and layout of your application to evolve independently of the views hosted within it.

The Composite Application Library supports the following controls to be exposed as regions:

  • System.Windows.Controls.ContentControl and derived controls
  • System.Windows.Controls.ItemsControl and derived controls
  • Controls derived from the class System.Windows.Controls.Primitives.Selector, such as the System.Windows.Controls.TabControl control

Note

For more information about regions, see the Region technical concept.

The following procedure describes how to add an ItemsControl control to the Shell window and associate a region to it. In a subsequent task, you will dynamically add a view to this region.

To add a region to the Shell window

  1. In the Shell.xaml file, add the following namespace definition to the root Window element. You need this namespace to use an attached property for regions; this attached property is defined in the Composite Application Library.

    xmlns:cal="https://www.codeplex.com/CompositeWPF"
    
  2. Replace the Grid control in the Shell window with an ItemsControl control named MainRegion, as shown in the following code.

    <Window x:Class="HelloWorld.Shell"
        xmlns:cal="https://www.codeplex.com/CompositeWPF"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        Title="Hello World" Height="300" Width="300">
    
    <ItemsControl Name="MainRegion"/>
    
    </Window>
    

    Figure 4 shows the Shell window in the Design view.

    Ff921141.b0a568b3-043a-45f6-9e92-61cbe4387361(en-us,PandP.10).png

    Figure 4
    Shell window with an ItemsControl control

  3. In the ItemsControl control definition, set the attached property cal:RegionManager.RegionName to "MainRegion," as shown in the following code. This attached property indicates that a region named MainRegion is associated to the control.

    <ItemsControl Name="MainRegion" cal:RegionManager.RegionName="MainRegion"/>
    

    Note

    When the Shell window is instantiated, Windows Presentation Framework resolves the value of the cal:RegionManager.RegionName attached property and invokes a callback in the RegionManager class. This callback creates a region and associates it with the ItemsControl control.

  4. (Optional) If you want to build and run the application now, change the value of the StartupUri attribute in the file App.xaml to "Shell.xaml," as shown in the following code, and run the application.

    <Application x:Class="HelloWorld.App"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        StartupUri="Shell.xaml">
        <Application.Resources>
    
        </Application.Resources>
    </Application>
    

Bootstrapper

The bootstrapper is responsible for the initialization of an application built using the Composite Application Library. Having a bootstrapper gives you more control of how the Composite Application Library components are wired up to your application. For example, if you have an existing application that you are adding the Composite Application Library to, you can initialize the bootstrapping process after the application is already running.

In a traditional Windows Presentation Foundation application, a startup Uniform Resource Identifier (URI) is specified in the App.xaml that launches the main window. In an application built using the Composite Application Library, it is the bootstrapper's responsibility. This is because the Shell window relies on services, such as the Region Manager, that need to be registered before the Shell window can be displayed. Additionally, the Shell window may rely on other services that are injected into its constructor.

The Composite Application Library includes a default abstract UnityBootstrapper class that handles this initialization using the Unity container. Typically, you use this base class to create a derived Bootstrapper class for your application that uses a Unity container. Many of the methods on the UnityBootstrapper class are virtual methods. You should override these methods as appropriate in your own custom bootstrapper implementation. If you are using a container other than Unity, you should write your own container-specific bootstrapper.

Note

To learn more about the bootstrapper process, see the Bootstrapper technical concept.

The following procedure explains how to set up the application's bootstrapper.

To set up the application's bootstrapper

  1. Add a new class file to the HelloWorld project named Bootstrapper.cs.

  2. Add the following using statements at the top of the file. You will use them to refer to elements referenced in the UnityBootstrapper class.

    using Microsoft.Practices.Composite.Modularity;
    using Microsoft.Practices.Composite.UnityExtensions;
    using System.Windows;
    
  3. Update the Bootstrapper class's signature to inherit from the UnityBootstrapper class.

    class Bootstrapper : UnityBootstrapper
    {
    }
    
  4. Override the CreateShell method in the Bootstrapper class. In this method, create an instance of the Shell window, display it to the user, and return it, as shown in the following code.

    protected override DependencyObject CreateShell()
    {
        Shell shell = new Shell();
        shell.Show();
        return shell;
    }
    

    Note

    You return the Shell object to have the UnityBootstrapper base class attach an instance of the region manager service to it. The region manager service is a service included in the Composite Application Library that manages regions in the application. By having a region manager instance attached to the Shell window, you can declaratively register regions from XAML code that will exist in the scope of the Shell window and child views. For more information about the region manager, see the Region technical concept.

  5. Override the GetModuleEnumerator method. In this template method, you typically create an instance of the module enumerator service, populate it with modules, and return it. The module enumerator service is a service included Composite Application Library; its interface is Microsoft.Practices.Composite.Modularity.IModuleEnumerator, and it is responsible for enumerating all the modules in the application. Because the application contains no modules at this point, the implementation of the GetModuleEnumerator method should simply return an instance of the module enumerator service, with no modules loaded. You can paste the following code in your Bootstrapper class to implement the method.

    protected override IModuleEnumerator GetModuleEnumerator()
    {
        return new StaticModuleEnumerator();
    }
    

    In the preceding code, an instance of the Microsoft.Practices.Composite.Modularity.StaticModuleEnumerator class is returned. This implementation of the module enumerator service statically enumerates modules. Module loading and module enumeration is described in more detail in "Task 3: Adding a Module" later in this topic.

    Note

    Several methods of the UnityBootstrapper base class can be overwritten to provide custom behavior. For more information, see the Bootstrapper technical concept.

  6. Open the file App.xaml.cs and initialize the bootstrapper in the handler for the Startup event of the application, as shown in the following code. By doing this, the bootstrapper code will we executed when the application starts.

    public partial class App : Applicationn
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
    
            Bootstrapper bootstrapper = new Bootstrapper();
            bootstrapper.Run();
        }
    }
    
  7. Open the file App.xaml and remove the attribute StartupUri. Because you are manually instantiating the Shell window in your bootstrapper, this attribute is not required. The code in the App.xaml file should look like the following.

    <Application x:Class="HelloWorld.App"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
        <Application.Resources>
    
        </Application.Resources>
    </Application>
    
  8. Build and run the application. You should see an empty Hello World window, as shown in Figure 5.

    Ff921141.05b0fb79-a974-4c16-a925-d589d56274ce(en-us,PandP.10).png

    Figure 5
    Hello World window

Task 3: Adding a Module

In this task, you will create a module and add it to your solution.

Background: Modularity Design Concept

Modularity is designing a system that is divided into a set of functional units (named modules) that can be composed into a larger application. A module represents a set of related concerns. It can include components such as views, business logic, and pieces of infrastructure, such as services for logging or authenticating users. Modules are independent of one another but can communicate with each other in a loosely coupled fashion.

A composite application exhibits modularity. Imagine an online banking program. The user can access a variety of functions, such as transferring money between accounts, paying bills, and updating personal information from a single UI. However, behind the scenes, each of these functions is a discrete module. These modules communicate with each other and with any back-end systems, such as database servers. Shell services integrate the input from the different modules and handle the communication between the modules and the user. The user sees an integrated view that looks like a single application.

Benefits of Modularity

Modularity provides the following benefits to development teams:

  • It promotes separation of concerns through allowing a high degree of separation between the application infrastructure and the business logic.
  • It allows different teams to independently develop each of the individual business logic and infrastructure components.
  • It allows parts of the application to separately evolve.
  • It promotes code re-use and flexibility because it allows business logic components and the application infrastructure to be incorporated into multiple solutions.
  • It provides an excellent architecture for the front-end integration of line-of-business systems or service-oriented systems into a task-oriented user experience.

Note

For more information about modularity, see the Modularity design concept and Module technical concept.

Modules

A module in the Composite Application Guidance for WPF is a logical unit in your application. Modules assist in implementing a modular design. These modules are defined in such a way that they can be discovered and loaded by the application at run time. Because modules are self-contained, they promote separation of concerns in your application. Modules can communicate with other modules and access services through various means. They reduce the friction of maintaining, adding, and removing system functionality. Modules also help testing and deployment.

Adding a module to your solution involves the following tasks:

  1. Creating a module. In this task, you create a module project with a module initializer class.
  2. Configuring how the module is loaded. In this task, you configure your application to load the module either statically or dynamically.

The following procedure describes how to create a module.

To create a module

  1. Add a new class library project to your solution. To do this, right-click the HelloWorld solution node in Solution Explorer, point to Add, and then click New Project. In the Project types list, select **Windows **inside the Visual C# node. In the Templates box, click Class Library. Finally, set the project's name to HelloWorldModule, and then click OK. Figure 6 illustrates how your solution should look like.

    Ff921141.5c50142c-1e53-48cd-b117-70f4d56d8677(en-us,PandP.10).png

    Figure 6
    Solution with a module named HelloWorldModule

  2. Add references in your module to the following Windows Presentation Foundation assemblies. To do this, right-click the HelloWorldModule project in Solution Explorer, and then click Add Reference. In the Add Reference dialog box, click the**.NET** tab, select the following assemblies, and then click OK.

    • PresentationCore.dll
    • PresentationFramework.dll
    • WindowsBase.dll
  3. Add references in your module to the following Composite Application Library assemblies. To do this, in Solution Explorer right-click the HelloWorldModule project and select Add Reference. In the Add Reference dialog, browse and select the assemblies in the Browse tab click OK:

    • Microsoft.Practices.Composite.dll
    • Microsoft.Practices.Composite.Wpf.dll

    A module initializer class is a class that implements the Microsoft.Practices.Composite.Modularity.IModule interface. This interface contains a single Initialize method that is called during the module's initialization process. The following code illustrates the IModule interface definition.

    namespace Microsoft.Practices.Composite.Modularity
    {
        public interface IModule
        {
            void Initialize();
        }
    }
    

    In the Initialize method of your module initializer class, you implement logic to initialize the module. For example, you can register views and services or add views to regions. In the subsequent steps, you will create a module initializer class for the HelloWorld module. You will add code to it in the next task.

  4. Rename the Class1.cs file to HelloWorldModule.cs. To do this, right-click the file in Solution Explorer, click Rename, set the new name, and then press ENTER. In the dialog box that asks if you want to perform a rename of all references to your class, click Yes.

  5. Open the file HelloWorldModule.cs and add the following using statement at the top. You will use it to refer to modularity elements provided by the Composite Application Library.

    using Microsoft.Practices.Composite.Modularity;
    
  6. Change the class signature to implement the IModule interface, as shown in the following code.

    public class HelloWorldModule : IModule
    {
    }
    
  7. Inside the HelloWorldModule class, add an empty definition of the Initialize method, as shown in the following code.

    public void Initialize()
    {
    
    }
    
  8. Add a Views folder to the HelloWorldModule project. In this folder, you will store your view implementations. To do this, right-click the HelloWorldModule project in Solution Explorer, point to Add, and then click New Folder. Change the folder name to Views.

    This step is recommended to organize your projects; this is useful when a module contains several artifacts. The following are other common folders that you can add to your module:

    • Services. In this folder, you store service implementations and service interfaces.
    • Controllers. In this folder, you store controllers.

    Figure 7 shows the solution with the HelloWorldModule module.

    Ff921141.16c1428e-185a-4df9-b898-534cdd946438(en-us,PandP.10).png

    Figure 7
    Solution with the HelloWorldModule

  9. Build the solution.

At this point, you have a solution based on the Composite Application Library with a module. However, the module is not being loaded into the application. The following section describes module loading and how you can load modules with the Composite Application Library.

Module Loading

Module loading is the process of loading modules into the application and initializing them. Module loading is a two-step process:

  1. Modules are discovered by the module enumerator service. The module enumerator creates a collection of metadata about those modules. This metadata can be consumed by the module loader service.
  2. The module loader service loads the modules, instantiates the module initializer classes of each module, and invokes the Initialize method on them.

Types of Module Loading

The Composite Application Library provides several ways to load modules. You can also provide your own custom implementation. The following are types of module loading supported out-of-the-box by the Composite Application Library:

  • Static module loading. When you statically load a module, the shell contains a reference to the module's assembly. Static module loading provides less decoupling of the shell with modules than dynamic module loading. However, in cases where decoupling modules from the shell is not a requirement, loading modules statically can reduce code complexity, simplify the application deployment, improve startup performance, and simplify debugging compared to dynamic loading.

  • Dynamic module loading. When you dynamically load a module, the shell does not contain a reference to the module's assembly; instead, modules are dynamically discovered at run time when the application starts. By doing this, the shell is decoupled from the modules. This implies that you can add, update, or remove modules from your application without recompiling the Shell project. Dynamic module loading requires a module's discovering and loading process to be executed during application startup, which may result in reduced startup performance compared to static module loading. In cases where decoupling modules from the shell is not a requirement, you should consider static module loading because it can reduce code complexity, simplify the application deployment, improve startup performance, and simplify debugging compared to dynamic loading.

    Note

    In this hands-on lab, static module loading is used. For more information about dynamic module loading, including detailed instructions about how to implement it, see How to: Dynamically Load Modules.

The following procedure explains how to configure the HelloWorldModule module to be statically loaded into the HelloWorld application.

To statically load the HelloWorld module

  1. In your Shell project, add a reference to the module project. To do this in Solution Explorer, right-click the HelloWorld project, and then click Add Reference. In the Add Reference dialog box, click the Projects tab, select the HelloWorldModule project, and then click OK.

  2. Open the Bootstrapper.cs file and explore the GetModuleEnumerator method. The method implementation is shown in the following code.

    protected override IModuleEnumerator GetModuleEnumerator()
    {
        return new StaticModuleEnumerator();
    }
    

    This method returns an instance of the StaticModuleEnumerator class. This type of module enumerator service is used to statically load modules—it implements the methods included in the IModuleEnumerator interface and adds an AddModule method for developers to manually register modules that should be loaded in the application. The signature of this method is shown in the following code.

    public StaticModuleEnumerator AddModule(Type moduleType, params string[] dependsOn);
    

    The AddModule method returns the same static module enumerator instance and takes the following parameters:

    • The module initializer class's type of module to load. This type must implement the IModule interface.
    • An array containing the names of the modules that the module depends on, if any. These modules will be loaded before your module to ensure your module dependencies are available when it is loaded.
  3. Update the GetModuleEnumerator to register the HelloWorldModule module with the static module enumerator instance before returning it. To do this, you can replace the GetModuleEnumerator implementation with the following code.

    protected override IModuleEnumerator GetModuleEnumerator()
    {
        return new StaticModuleEnumerator()
          .AddModule(typeof(HelloWorldModule.HelloWorldModule));
    }
    
  4. Build and run the solution. To verify that the HelloWorldModule module gets initialized, add a breakpoint to the Initialize method of the HelloWorldModule class. The breakpoint should be hit when the application starts.

Note

For more information about modules, see the Module technical concept.

Task 4: Adding a View

In this task, you will create and add a view to the HelloWorldModule module. Views are objects that contain visual content. Views are often user controls, but they do not have to be user controls. Adding a view to your module involves the following tasks:

  1. Creating the view. In this task, you implement the view by creating the visual content and writing code to manage the UI elements in the view.
  2. Showing the view in a region. In this task, you obtain a reference to a region and add the view to it.

The following procedure describes how to create a view.

To create a view

  1. Add a new WPF user control to your module. To do this, right-click the Views folder in Solution Explorer, point to Add, and then click New Item. In the Add New Item dialog box, select the User Control (WPF) template, set the name to HelloWorldView.xaml, and then click Add.

  2. Add a "Hello World" text block to the view. To do this, you can replace your code in the file HelloWorldView.xaml with the following code.

    <UserControl x:Class="HelloWorldModule.Views.HelloWorldView"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
        <Grid>
    <TextBlock Text="Hello World" Foreground="Green" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Calibri" FontSize="24" FontWeight="Bold"></TextBlock>
        </Grid>
    </UserControl>
    
  3. Save the file.

Note

To keep this hands-on lab simple, the procedure did not explain how to create a view following the Model-View-Presenter pattern. This pattern separates the responsibilities for the visual display and the event handling behavior into different classes named, respectively, the view and the presenter. For more information about the Model-View-Presenter pattern and instructions about how to implement it, see How to: Create a View with a Presenter.

Region Manager

The region manager service** **is responsible for maintaining a collection of regions and creating new regions for controls. This service implements the Microsoft.Practices.Composite.Regions.IRegionManager interface. Typically, you interact directly with this service to locate regions in a decoupled way through their name and add views those regions. By default, the UnityBootstrapper base class registers an instance of this service in the application container. This means that you can obtain a reference to the region manager service in the HelloWorld application by using dependency injection.

The following procedure explains how to obtain an instance of the region manager and add the HelloWorldView view to the shell's main region.

To show the view in the shell

  1. Open the HelloWorldModule.cs file.

  2. Add the following using statement at the top of the file. You will use it to refer to the region elements in the Composite Application Library.

    using Microsoft.Practices.Composite.Regions;
    
  3. Create a private read-only instance variable to hold a reference to the region manager. To do this, paste the following code inside the class body.

    private readonly IRegionManager regionManager;
    
  4. Modify the HelloWorldModule class's constructor to obtain a region manager instance through constructor dependency injection and store it in the regionManager instance variable. To do this, the constructor has to take a parameter of type Microsoft.Practices.Composite.Regions.IRegionManager. You can paste the following code inside the class body to implement the constructor.

    public HelloWorldModule(IRegionManager regionManager)
    {
      this.regionManager = regionManager;
    }
    
  5. In the Initialize method, obtain a reference to the shell's main region. You obtain a reference to a region by using the Regions property of the region manger service passing the region's name as the search key, as shown in the following code.

    public void Initialize()
    {
        IRegion mainRegion = this.regionManager.Regions["MainRegion"];
    }
    

    Note

    The region's name must match the name defined in the RegionName attribute of the region.

  6. Create an instance of the HelloWorldView view and add it to the main region. To do this, instantiate the view and invoke the Add method on the region passing the new instance of HelloWorldView view as the parameter, as shown in the last two lines of the following method definition.

    public void Initialize()
    {
    IRegion mainRegion = this.regionManager.Regions["MainRegion"];    Views.HelloWorldView view = new Views.HelloWorldView();mainRegion.Add(view);
    }
    

    In the preceding code, the Add method adds the view to the region, but it does not ensure that the view is displayed. For example, if the underlying UI element of the region was a TabControl control, the view would be added to the control as a new tab, but the tab would not necessarily receive focus. Thus, it is recommended that you explicitly activate the view when you want it to be displayed in the user interface.

  7. Activate the HelloWorldView view. To do this, invoke the Activate method on the region passing the view as the parameter. The following code shows the full Initialize method implementation.

    public void Initialize()
    {
    IRegion mainRegion = this.regionManager.Regions["MainRegion"];
        Views.HelloWorldView view = new Views.HelloWorldView();
        mainRegion.Add(view);
        mainRegion.Activate(view);
    }
    
  8. Build and run the application. You should see the Hello World window with a "Hello World" message, as illustrated in Figure 8.

    Ff921141.07a13161-d6cc-4bc6-9405-1a4ca1afa63c(en-us,PandP.10).png

    Figure 8
    Hello World message

Note

To open the final solution in Visual Studio, run the Open Hello World Solution.bat file.

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.