How to: Create a View with a Presenter

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.

Overview

The Model-View-Presenter pattern separates the responsibilities for the visual display and the event handling behavior into different classes named, respectively, the view and the presenter. The view class manages the controls on the user interface and it forwards user events to a presenter class. The presenter contains the logic to respond to the events, update the model (business logic and data of the application) and, in turn, manipulate the state of the view.

This Supervising Controller pattern is a variant of the Model-View-Presenter pattern and is used throughout this guidance. This variant permits using data binding to enable direct communication between the view and the model. By using the Supervising Controller pattern in a composite WPF application, developers can use the data-binding capabilities provided by Windows Presentation Foundation (WPF). For more information about the Supervising Controller pattern, see Supervising Controller.

This topic describes how to create a view following the Model-View-Presenter pattern.

Prerequisites

This topic assumes that you already have a solution based on the Composite Application Library with a module.

Steps

The typical implementation process of the Model-View-Presenter pattern includes the following tasks:

  1. Implementing a presenter class. The presenter should handle user events, update the model, and manipulate the state of the view.
  2. Implementing a view interface. The view interface should expose the view's state elements.
  3. Implementing a view class. The view contains user interface artifacts. The view should forward user events to the presenter and expose properties that allow the presenter to manipulate the view's state.

Figure 1 illustrates an example of a solution that implements the Model-View-Presenter pattern.

Ff921167.8b48bd07-0f4f-4ffc-8cfd-f2c14a3d57aa(en-us,PandP.10).png

Figure 1
Solution with an Model-View-Presenter implementation

The following procedure describes how to implement a presenter class and a view interface.

To implement a presenter class and a view interface

  1. Add a new interface file to your module; this file will contain the interface the view will implement and through which the presenter will communicate to the view. Name the file using the format IViewNameView.cs, where ViewName is your view's name, for example, IEmployeesView.cs.

    Note

    It is recommended, for organization purposes, to create a folder in your module to group views and optionally, to create a subfolder for each view to store the corresponding presenter, the view interface, and the view implementation files.

  2. Add a new class file to your module; this file will contain the presenter class definition. Name the file using the format ViewNamePresenter.cs,** **where ViewName is your view's name, for example, EmployeesPresenter.cs.

  3. Using constructor dependency injection, obtain a reference to an instance of the view and store it in an instance variable. To do this, update the presenter class constructor to take a parameter of the type of the view interface, as shown in the following example code (in this example, it is assumed that the class is instantiated using a dependency injection container).

    class EmployeesPresenter
    {
      private IEmployeesView view;
    
      public EmployeesPresenter (IEmployeesView view)
      {
        this.view = view;
      }
    }
    
  4. Add methods to the presenter to handle user gestures, update the model, and manipulate the state of the view. To do this, consider the following:

    • Usually the presenter is implemented using Test-Driven Development (TDD).
    • To test the presenter in isolation, make sure the presenter always references the view interface instead of the view concrete implementation. By doing this, you can easily replace the view with a mock implementation when writing and running tests. A similar approach can be followed for model artifacts.
    • Implementing the presenter first allows you to focus on the business logic and application functionality independently from the user interface implementation.
    • When implementing the presenter, you also need to add members to the view interface and create (or use) model objects to express the interaction between the view, the model, and the presenter.
  5. Add members to the view interface. To do this, consider the following:

    • The view interface usually contains one or more properties for the presenter to set or query the view's state. For example, a view could expose an Employee property that allows the presenter to set the employee that the view should display. Another approach consists of using the Presentation Model pattern. In this case, the view interface contains a single property for the presenter to set the presentation model. A different approach consists of exposing methods on the view interface. For example, the presenter could invoke a method named ShowEmployee(Employee) that indicates to the view that it has to display the employee passed by parameter.

      Note

      For more information about the Presentation Model pattern, see Presentation Model.

    • Exposing properties over methods in the view usually keeps the presenter simpler because it does not need to know about view implementation details, such as when data is to be bound to user interface controls.

    • The view can interact with the presenter by directly invoking methods on it or by raising events. If the view interacts with the presenter by raising events, the view interface will include event declarations.

    The following example code extracted from the UI Composition QuickStart illustrates a presenter class definition and its corresponding view interface.

    public class EmployeesDetailsPresenter : IEmployeesDetailsPresenter
    {
        public EmployeesDetailsPresenter(IEmployeesDetailsView view)
        {
            this.View = view;
        }
    
        public IEmployeesDetailsView View { get; set; }
    
        public void SetSelectedEmployee(BusinessEntities.Employee employee)
        {
            EmployeesDetailsPresentationModel model = new EmployeesDetailsPresentationModel();
            model.SelectedEmployee = employee;
            this.View.Model = model;
        }
    }
    
    public interface IEmployeesDetailsView
    {
        EmployeesDetailsPresentationModel Model { get; set; }
    }
    

    For more examples of presenter classes and view interfaces, see the implementation of the views EmployeesDetailsView, EmployeesListView, and EmployeesView in the UI Composition QuickStart and the views NewsReaderView and TrendLineView in the Stock Trader Reference Implementation.

The following procedure explains how to create a view implementation.

To create a view implementation

  1. Add a new User Control (WPF) to your module. This user control will be the view implementation. Name the user control file using the format ViewNameView.xaml, where ViewName is your view's name, for example, EmployeesView.xaml.

  2. Add user interface elements to the view required for your scenario.

  3. Open the view's code behind file and update the class signature to implement your view interface. The following code shows the class definition for a view named EmployeesView that implements the IEmployeesDetailsView interface.

    public partial class EmployeesDetailsView : UserControl, IEmployeesDetailsView
    {
        ...
    }
    
  4. Implement the members required by the view interface. When doing this, consider the following:

    • The view should forward user events to the presenter and expose properties that allow the presenter to manipulate the view's state.
    • There are several ways that the view can forward user gestures to the presenter. In one approach, the view directly invokes the presenter's methods. This approach requires you to implement additional methods in the presenter and couples the view with a particular presenter. Another approach consists of having the view raise events when user actions occur. This approach requires code in the view to raise events and code in the presenter to subscribe to the view events. The benefit to the second approach is that there is less coupling between the view and the presenter than with the first approach.

The following code shows the code behind file of the EmployeesDetailsView view extracted from the UI Composition QuickStart.

public partial class EmployeesDetailsView : UserControl, IEmployeesDetailsView
{
    public EmployeesDetailsView()
    {
        InitializeComponent();
    }

    public EmployeesDetailsPresentationModel Model
    {
        get { return this.DataContext as EmployeesDetailsPresentationModel; }
        set { this.DataContext = value; }
    }

    ...
}

Outcome

You will have a new view with presenter (and view interface) in your module.

Next Step

After you create a view with presenter, a typical task to perform next is to show the view in a region. For details about how to do this, see How to: Show a View in a Shell Region and How to: Show a View in a Scoped Region.

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.