Export (0) Print
Expand All

WPF Hands-On Lab: Getting Started with the Composite Application Library

Purpose

In this lab, you will learn the basic concepts of the Composite Application Guidance and apply them to create a Composite Application Library solution that you can use as the starting point for building a composite Windows Presentation Foundation (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 and Silverlight.
  • You will create a new solution based on the Composite Application Library.
  • You will create and load a module.
  • 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.Presentation.dll
  • Microsoft.Practices.Composite.UnityExtensions.dll
  • Microsoft.Practices.ObjectBuilder2.dll
  • Microsoft.Practices.ServiceLocation.dll
  • Microsoft.Practices.Unity.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.Presentation. 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:

    Desktop & Silverlight - Open Composite Application Library.bat

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

Procedures

This lab includes the following tasks:

  • Task 1: Understanding the Composite Application Guidance for WPF and Silverlight
  • 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.

Ff650825.note(en-us,PandP.10).gifNote:
The instructions of this hands-on lab are based on the HelloWorld solution. To open the solution in Visual Studio, run the file Desktop only - Open QS - Hello World QuickStart.bat.

Task 1: Understanding the Composite Application Guidance for WPF and Silverlight

The Composite Application Guidance for WPF and Silverlight is a set of guidance for developing complex WPF and Silverlight 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.

Ff650825.fa91b811-ce24-4790-9625-5e96f7e3ba55(en-us,PandP.10).png

Figure 1

Composite application

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 the 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. 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.Desktop, 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.

    Ff650825.31792356-e95c-4b88-a0b6-e2785d56e07b(en-us,PandP.10).png

    Figure 2

    HelloWorld project
  2. Using Windows Explorer, create a folder named Library.Desktop inside your solution's folder, and then 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.Presentation.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.
    • Microsoft.Practices.ServiceLocation.dll. This assembly contains the Common Service Locator interface used by the Composite Application Guidance to provide an abstraction over Inversion of Control containers and service locators; therefore, you can change the container implementation with ease.
  3. In the HelloWorld project, add references to the assemblies listed in the preceding 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.
Ff650825.note(en-us,PandP.10).gifNote:
For IntelliSense to be available for the Composite Application Library, the XML documentation files for each of these assemblies must be placed in the same directory as the referenced assemblies.

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 appearance 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.

    Ff650825.3722e221-b4b8-43fa-a355-afdac82e1d09(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.Desktop.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="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://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 names; they support dynamically adding or removing views 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
Ff650825.note(en-us,PandP.10).gifNote:
For more information about regions, see the UI Composition 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 that is defined in the Composite Application Library.
    xmlns:cal="http://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="http://www.codeplex.com/CompositeWPF"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://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.

    Ff650825.62f834c1-516e-46f7-8b53-78fb7604f7dd(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"/>
    
    Ff650825.note(en-us,PandP.10).gifNote:
    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.

Bootstrapper

The bootstrapper is responsible for the initialization of an application built using the Composite Application Library. When you have a bootstrapper, you have 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 file; the URI launches the main window. In an application built using the Composite Application Library, it is the bootstrapper's responsibility to launch the main window. 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.

Ff650825.note(en-us,PandP.10).gifNote:
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 named Bootstrapper.cs to the HelloWorld project.
  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;
    }
    
    Ff650825.note(en-us,PandP.10).gifNote:
    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 UI Composition technical concept.

  5. Override the GetModuleCatalog method. In this template method, you typically create an instance of a module catalog, populate it with modules, and return it. The module catalog interface is Microsoft.Practices.Composite.Modularity.IModuleCatalog, and it contains metadata for all the modules in the application. Because the application contains no modules at this point, the implementation of the GetModuleCatalog method should simply return an instance of the module catalog, with no modules loaded. You can paste the following code in your Bootstrapper class to implement the method.
    protected override IModuleCatalog GetModuleCatalog()
    {
        ModuleCatalog catalog = new ModuleCatalog();
        return catalog;
    }
    

    In the preceding code, an instance of the Microsoft.Practices.Composite.Modularity.ModuleCatalog class is returned. This implementation of the module catalog is used to define the application's modules. Module loading and module catalogs are described in more detail in "Task 3: Adding a Module" later in this topic.

    Ff650825.note(en-us,PandP.10).gifNote:
    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 : Application
    {
        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="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://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.

    Ff650825.8a767695-2e26-415a-a937-190d066a964d(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. For example, consider 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 components 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.
Ff650825.note(en-us,PandP.10).gifNote:
For more information about modularity, see the Modularity design concept and the Module technical concept.

Modules

A module in the Composite Application Guidance for WPF and Silverlight is a logical unit in your application. Modules assist with 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 with 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.

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.Desktop solution node in Solution Explorer, point to Add, and then click New Project. In the Project types list, select Windows in 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.

    Ff650825.3979abe5-6c65-4ef3-905e-d5e2c3387cb2(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, click 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, right-click the HelloWorldModule project in Solution Explorer, and then click Add Reference. In the Add Reference dialog box, click the Browse tab, click the following assemblies, and then click OK:
    • Microsoft.Practices.Composite.dll
    • Microsoft.Practices.Composite.Presentation.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, type 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 of the file. 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. In 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.

    Ff650825.91a3a3f3-20ec-4ff5-85d9-99ff786bd389(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 Process

Modules go through a three-step process during application start up:

  1. Modules are discovered by the module catalog. The module catalog contains a collection of metadata about those modules. This metadata can be consumed by the module manager service.
  2. The module manager service coordinates the modules initialization. It manages the retrieval and the subsequent initialization of the modules. It loads modules—retrieving them if necessary—and validates them.
  3. Finally, the module manager instantiates the module and calls the module's Initialize method.

Populating the Module Catalog

The Composite Application Library provides several ways to populate the module catalog. You can also provide your own custom implementation. In Windows Presentation Foundation (WPF), the following are types of populating the module catalog supported, without modification, by the Composite Application Library:

  • Populating the module catalog from code. This is the most straightforward method of populating the module catalog. In this approach, the module information is added to the module catalog in code. If you directly reference the modules, you can use the module type to add the module. However, directly referencing modules results in a less decoupled design. If you do not directly reference modules from the shell, you must provide the fully qualified type name and the location of the assembly.

    Another advantage of this approach is that you can easily add conditional logic to determine which modules should be loaded.

  • Populating the catalog from a XAML file. Another approach is to declaratively specify the kind of module catalog to create and which modules to add to it; you do this by creating a ModuleCatalog.xaml file. Typically, the XAML file is added as a resource to your shell; from a technical perspective, this approach is very similar to defining the module catalog from code.
  • Populating the catalog from a Configuration file. In WPF, you can specify the module information in the App.config file. The advantage of this approach is that because this configuration file is not compiled with the application, new modules can be easily added without recompiling the shell.
  • Populating the catalog from a Directory. In WPF, you can also declare the modules in a directory and use the DirectoryModuleCatalog to look for modules in that designated folder.

    This approach requires you to configure modules using attributes in code; this is the easiest way to add and remove modules from your application.

    Ff650825.note(en-us,PandP.10).gifNote:
    In this hands-on lab, the catalog is populated from code.
    For more information about populating the catalog from a XAML file, including how to implement it, see How to: Populate the Module Catalog from XAML.
    For more information about populating the catalog from a configuration file or a directory, including how to implement it, see How to: Populate the Module Catalog from a Configuration File or a Directory in WPF.

The following procedure explains how to populate the catalog from code to load the HelloWorldModule module into the HelloWorld.Desktop application.

To populate the module catalog with the HelloWorld module from code

  1. In your Shell project, add a reference to the module project. To do this in Solution Explorer, right-click the HelloWorld.Desktop project, and then click Add Reference. In the Add Reference dialog box, click the Projects tab, click the HelloWorldModule project, and then click OK.
  2. Open the Bootstrapper.cs file and explore the GetModuleCatalog method. The method implementation is shown in the following code.
    protected override IModuleCatalog GetModuleCatalog()
    {
        ModuleCatalog catalog = new ModuleCatalog();
        return catalog;
    }
    

    This method returns an instance of the ModuleCatalog class. This type of module catalog service is used to define the application's modules from code—it implements the methods included in the IModuleCatalog 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 ModuleCatalog AddModule(Type moduleType, InitializationMode initializationMode, params string[] dependsOn)
    

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

    • The module initializer class's type of module to load. This type must implement the IModule interface.
    • The Initialization mode. This parameter indicates how the module will be initialized. The possible values are InitializationMode.WhenAvailable and InitializationMode.OnDemand.
    • 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 GetModuleCatalog method to register the HelloWorldModule module with the module catalog instance before returning it. To do this, you can replace the GetModuleCatalog implementation with the following code.
    protected override IModuleCatalog GetModuleCatalog()
    {
        ModuleCatalog catalog = new ModuleCatalog()
            .AddModule(typeof(HelloWorldModule.HelloWorldModule));
        return catalog;
    }
    
    Ff650825.note(en-us,PandP.10).gifNote:
    The WhenAvailable initialization mode is the default value if no initialization mode is specified.

  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.
Ff650825.note(en-us,PandP.10).gifNote:
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="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://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.
Ff650825.note(en-us,PandP.10).gifNote:
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, including 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 to 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, invoke the RegisterViewWithRegion method on the RegionManager instance. This method registers a region name with its associated view type in the region view registry; the registry is responsible for registering and retrieving of these mappings.

    The RegisterViewWithRegion method has two overloads. When you want to register a view directly, you use the first overload that requires two parameters, the region name and the type of the view. This is shown in the following code.

    public void Initialize()
    {
        regionManager.RegisterViewWithRegion("MainRegion", typeof(Views.HelloWorldView));
    }
    

    The UI composition approach used in the preceding code is known as View Discovery. When using this approach, you specify the views and the region where the views will be loaded. When a region is created, it asks for its associated views and automatically loads them.

    Ff650825.note(en-us,PandP.10).gifNote:
    The region's name must match the name defined in the RegionName attribute of the region.

  6. Build and run the application. You should see the Hello World window with a "Hello World" message, as illustrated in Figure 8.

    Ff650825.194d18f1-4662-4fbb-8e20-2f71c6522eba(en-us,PandP.10).png

    Figure 8

    Hello World message
Ff650825.note(en-us,PandP.10).gifNote:
To open the solution that results from performing the steps in this Hands-on Lab in Visual Studio, run the file Desktop only - Open QS - Hello World QuickStart.bat.

More Information

For a complete list of How-to topics included with the Composite Application Guidance, see Development Activities.


Home page on MSDN | Community site

Show:
© 2014 Microsoft