Export (0) Print
Expand All
This topic has not yet been rated - Rate this topic

User Interface Process (UIP) Application Block - Version 2.0

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.
 

patterns & practices Developer Center

Microsoft Corporation

April 2004

Summary: Chapter 2 discusses the design of the UIP application block.

Contents

UIP Application Block Architecture
Elements of the UIP Application Block
Conclusion

The UIP Application Block provides you with an infrastructure that allows you to write complex user interface navigation and workflow processes. Additionally, you can reuse and extend these processes as your application evolves. This chapter examines the design of the UIP Application Block to help you understand how to use the block in your environment.

UIP Application Block Architecture

As mentioned in Chapter 1, the UIP Application Block is based on the model-view-controller (MVC) pattern. Each of the MVC objects is represented in the UIP Application Block in the following ways:

  • Model — Implemented in the State class. This stores both user information and control information within the user interface process.
  • View — Implemented in the WebFormView, WindowsFormView, and WindowsFormControlView classes. These are used to create views in your application.
  • Controller — Implemented in classes that derive from the ControllerBase abstract class. These classes are responsible for the starting of, navigation within, and ending of a user interface process.

The UIP Application Block contains several classes and interfaces that combine to provide an infrastructure you can use with your own applications. The following diagram illustrates the design of the UIP Application Block, showing the main components of the block, and how they interact with components provided by your organization.

Ff650820.uipc0201(en-us,PandP.10).gif

Figure 2.1: UIP Application Block design

Table 2.1 describes the elements shown in Figure 2.1.

Table 2.1: UIP Application Block Elements

Block elementProvided byDescription
Your ApplicationYour organizationContains code for calling the appropriate start task method on the UIP manager.
Configuration FileYour organizationContains application configuration information.
Your Controllers,
Controller Base
Your organization (UIP Application Block provides the ControllerBase abstract class you can use to create the controller). Controls the navigation between views and acts as a facade between the user interface layer and the business layer. Provides access to the business logic of your application.
Services, Business ComponentsYour organizationThe services (such as Web or data services) and business logic of your application.
UIP ManagerUIP Application BlockProvides entry points to the UIP Application Block for starting or loading a task with a variety of navigators.
NavigatorUIP Application BlockManages transitions between views and determines the appropriate view, asking the view manager to activate it.
UIP ConfigurationUIP Application BlockRetrieves, verifies, and stores the information contained in the application configuration file.
Your Views, ViewsYour organization (UIP Application Block provides view classes you can inherit from to create your application's views.)User interface elements for user interaction.
View ManagerUIP Application Block provides some implementations.Creates and activates views as requested by the navigator.
StateUIP Application Block provides an implementation.Maintains user process state and maintains the current view in the task.
StatePersistence ProviderUIP Application Block provides some implementations.Captures the state to be stored in the state persistence store.
State Persistence StoreYour organizationPreserves the state.

The UIP Application Block abstracts the creation of the view to a view manager, which ensures that you can create and configure views that appear consistent to UIP. This allows you to use the same state management and configuration capabilities for both Microsoft® Windows® operating system and Web environments. For more information about the elements in Table 2.1, see "Elements of the UIP Application Block," later in this chapter.

Note   In many cases, you must write separate presentation layer code for Windows-based applications and Web applications. This is because the nature of user interaction can differ substantially between a Windows-based application and a Web application.

At a high level, the UIP Application Block displays views as follows:

  1. Your application calls the appropriate StartNavigationTask, StartOpenNavigationTask, or StartUserControlsTask method on the UIP manager. After a task is started, creation of views, navigation, and state management are performed through UIP.
  2. The UIP manager creates the appropriate navigator (for example, the graph navigator, user controls navigator, or wizard navigator) and passes the necessary information to the navigator.
  3. The navigator calls the UIPConfigSettings class to retrieve configuration information parsed from the configuration file.
  4. The navigator creates the appropriate view manager, based on the type of views being used (as specified in the configuration file).
  5. The navigator creates or loads the task.
  6. The navigator determines which view to activate.
  7. The navigator issues a NavigateEvent event through the UIP manager. This provides the current and next view and can be used by applications external to the UIP Application Block.
  8. The navigator calls the Save method on the State object; the State object then asks the appropriate state persistence provider to save the state.
  9. The navigator calls the ActivateView method on the appropriate view manager and passes the view name to the view manager. The ActivateView method is responsible for creating the controller and displaying the view. Exactly how this occurs varies depending on whether the application is Windows Forms or Web-based.
  10. After the view displays, the user is in control and UIP does nothing further until the user performs an action on the user interface (for example, clicking a button).
  11. The user performs an action, and the event causes a method to be called on the view, which in turn calls a method on the controller. Depending on the user action, the controller does one of the following:
    • Perform or delegate a function related to business logic (such as saving information to the database) that causes the view to refresh and change state. If the function causes a modification to the current state, the State class will raise the StateChanged event, to notify any interested listeners of changes that have occurred to the state.
    • Call the Navigate method on the navigator to transition to the next view or user control, and update the State object.
    • Call the SuspendTask method to clear the State object from memory but not clear it from the state persistence storage.
    • Call the CompleteTask method to clear the State object from both the memory and state persistence storage.
    • Call the OnstartTask method to chain or link tasks.

Elements of the UIP Application Block

To understand the design of the UIP Application Block, it is important to examine in more detail each of the elements that make up the block. The following paragraphs discuss these elements.

UIP Manager

To use the functionality of the UIP Application Block, your application must call the UIP manager to start a UIP task and start the appropriate navigator. The UIPManager class contains static methods you can use to start tasks with a variety of navigators, as shown in Table 2.2.

Table 2.2: UIPManager Public Methods That Start a Navigator and Task

MethodsDescription
StartNavigationTaskStarts a graph navigator-based task. The name of the graph navigator in the configuration file must be provided.
StartOpenNavigationTaskStarts an open navigator-based task with no restrictions on transitions between views. An initial view name must be specified.
StartUserControlsTaskStarts a user controlled navigator-based task. The name of the user controls navigator in the configuration file must be provided.

These methods are overloaded so you can call the same method with different parameters. In some cases you will create a new task and in others you will load a pre-existing task. The UIP manager creates an instance of the appropriate navigator depending on the parameters that are sent to the StartNavigationTask, StartOpenNavigationTask, or StartUserControlsTask method. For more information about how to start a task from your application, see "Starting and Resuming Tasks" in Chapter 3, "Developing Applications with the UIP Application Block."

The UIPManager class also allows you to listen for navigation changes through the NavigationEvent event. A NavigationEvent event is raised after the Navigate method is called on the Controller class, but before actual navigation takes place. This gives you one last opportunity to perform a function before the user is taken to the next view. For more information, see "Raising Navigation Events" in Chapter 3, "Developing Applications with the UIP Application Block."

UIP Configuration Classes

The UIP Application Block uses the UIPConfigHandler, UIPConfigSettings, and UIPConfiguration classes to retrieve and maintain information from the configuration file. The UIPConfigHandler class implements the .NET Framework IConfigSectionHandler interface and is used to validate and parse the <uipConfiguration> section of an application configuration file. It retrieves and validates the configuration information against the XML schema and creates an instance of an XML node that represents the configuration information for the block. The UIPConfigSettings class parses the XML node retrieved from the UIPConfigHandler and loads the objects that an application using the block needs to function. There is one instance of the UIPConfigSettings object per application. The UIPConfiguration class exposes an instance of the UIPConfigSettings object to the application.

Navigator

The Navigator class is an abstract class that coordinates the navigation between views and provides functionality common to all of the navigators. The Navigator class contains five properties, as shown in Table 2.3.

Table 2.3: Navigator Class Properties

PropertyDescription
ViewManagerProvides access to the view manager associated with the navigator.
NameProvides the name of the navigator.
CurrentStateProvides the current state of the navigator.
CacheExpirationModeSpecifies the expiration mode of the State cache for this task.
CacheExpirationIntervalSpecifies the interval used to expire entries in the State cache.

Two important methods of the Navigator class are the Navigate method and the OnStartTask method. The controller tells the navigator which node or view to transition to by calling the Navigate method, and then passing the node or view name as a parameter. The OnStartTask method handles any StartTask events started by the Controller and is used to link tasks together. For more information about linking tasks, see "Linking Tasks" in Chapter 3, "Developing Applications with the UIP Application Block."

The Navigator class behaves slightly differently, depending on the parameters that are passed to the appropriate StartNavigationTask, StartOpenNavigationTask, or StartUserControlsTask method:

  • If no task ID or task object has been created, the navigator assumes it is creating a new task. The navigator creates a task ID, calls the Create method on the state factory to create the State object, calls the Create method on the state persistence factory to create the StatePersistence object, and sets the task ID on the task.
  • If the task object has been created but there is no task ID, the navigator creates a task ID and passes that back to the task. The navigator then calls the Create method on the state factory to create the State object, calls the Create method on the state persistence factory to create the StatePersistence object and sets the task ID on the task.
  • If there is already a valid task object and corresponding task ID, the navigator calls the Load method on the State factory class to retrieve the task from the appropriate state persistence provider, and passes the task ID to the State object.

For more information about starting tasks, see "Starting and Resuming Tasks" in Chapter 3, "Developing Applications with the UIP Application Block."

Note   You should only be concerned with how to maintain task IDs if you want to persist and load the state at a later date. Your task IDs can be maintained in a table or a list, or if you are using SQL server state persistence, you can use a SQL database.

The Navigator class also behaves differently, depending on which view it activates:

  • If your application is showing its first view, the view is specified in the configuration file, or, in the case of open navigation, as a parameter in the StartOpenNavigationTask method.
  • If your application is restoring a view from a saved state, the navigator determines the current view from that saved state and sets it as the start view.
  • If your application is showing any view other than the first view, the navigator retrieves the configuration information for the view from the UIPConfigSettings object, sets the current view property on the state object to be the name of the view, clears the navigateValue property, saves the state, and calls the ActivateView method on the appropriate view manager.

For Web applications, the navigator also uses conditional logic to test whether the user is allowed to navigate to a view by specifying a URL or by clicking on the back or forward buttons. Before the navigator creates the controller for the view in the GetController method, the code performs the following steps:

  1. The navigator calls the ActivateViewInStateIfNecessary internal method.
  2. This method calls the IsRequestCurrentView on the view manager to determine if the requested view is the same as the view on the current state.
  3. If the views differ, the navigator verifies that the AllowBackButton attribute in the configuration file is enabled.
  4. If AllowBackButton is not enabled, the navigator reloads the view in the current state, presenting the user with the same view as before.
  5. If AllowBackButton is enabled, the navigator performs an additional check for graph navigators to ensure the user is not navigating outside of the navigation graph. If the view does not exist in the navigation graph, the navigator reloads the view in the current state, presenting the user with the same view as before.
  6. If the view does exist in the navigation graph or if a navigation graph is not being used, the navigator loads the requested view.

Four navigators are supplied with the UIP Application Block, each derived from the Navigator class:

  • GraphNavigator — Allows you to define the process of views and permitted transitions for a given task. This applies to Windows-based applications and Web applications.
  • OpenNavigator — Allows you to freely navigate between views where there are no restrictions on transitions between views. This applies to Windows-based applications and Web applications.
  • UserControlsNavigator — Allows you to define the views and permitted transitions between various controls on a Windows Form. This only applies to Windows-based applications.
  • WizardNavigator — Allows you to define the views and allowed transitions in a wizard. This only applies to Windows-based applications.
    Note   The WizardNavigator class derives from the GraphNavigator class.

You can only specify one navigator per task. If you want to transition between navigators, you need to create a new task to do so. Each navigator is designed slightly differently, so it is useful to look at each at each in turn.

Graph Navigator

The GraphNavigator class is derived from the Navigator class and coordinates the navigation between views by using a navigation graph. Navigation graphs encapsulate workflow functionality through a list of views and allowed transitions. They allow you to determine which views exist in a user interface process and the transitions that are valid from each node. Navigation graphs contain a start node, an end node, and zero or more nodes in between. The path between the start and end can be a simple linear path, or include branching and circular routes. This can be seen in the sample navigation graph shown in Figure 2.2.

Ff650820.uipc0202(en-us,PandP.10).gif

Figure 2.2: Sample navigation graph

You can create and begin a graph navigator by calling the StartNavigationTask method on the UIP manager and passing the name of the navigation graph in the configuration file as a parameter, along with task information if the navigator reloads a task. For more information, see "Starting and Resuming Tasks with the Graph Navigator" in Chapter 3, "Developing Applications with the UIP Application Block." When the StartNavigationTask method is called, the graph navigator ensures that the task, state object, and state persistence provider are created. The controller tells the graph navigator which node it should transition to by calling the Navigate method and passing the node name as a parameter. The navigator checks the navigation graph in the UIPConfigSettings class to ensure that the transition is valid, and if it is not, generates an exception. A valid node is either listed as a child of the current node or specified in a shared transition.

When using the UIP Application Block, you define navigation graphs in the <navigationGraph> section of your XML configuration file. Each graph contains a node element for each view, and the node element contains <navigateTo> child elements, which define the different paths that can be taken from that view. The following code shows the XML required to follow the paths shown in Figure 2.2, earlier in this section.

<navigationGraph
    iViewManager="WinFormViewManager"
    name="Shopping"
    state="State"
    statePersist="SqlServerPersistState"
    startView="cart">
  <node view="cart">
    <navigateTo navigateValue="resume" view="browsecatalog" />
    <navigateTo navigateValue="checkout" view="checkout" />
    <navigateTo navigateValue="fail" view="error" />
  </node>
  <node view="browsecatalog">
    <navigateTo navigateValue="addItem" view="cart"/>
    <navigateTo navigateValue="fail" view="error" />
  </node>
  <node view="error">
    <navigateTo navigateValue="resume" view="cart" />
  </node>
  <node view="checkout">
    <navigateTo navigateValue="passCheckout" view="congrats" />
    <navigateTo navigateValue="failCheckout" view="checkout" />
  </node>
  <node view="congrats">
    <navigateTo navigateValue="resume" view="browsecatalog" />
  </node>
</navigationGraph>

Shared Transitions

An application may have views that are a common transition point for many (or all) nodes within the navigation graph. These views are named shared transitions. This functionality is useful if, for example, you want errors that are generated anywhere in the navigation graph to transition to a common view or if you want to display a common help page. This has the same effect as repeating the navigateTo element in the shared transitions for each node in the navigation graph. Any node-specific transitions override the global shared transitions.

Open Navigator

In some cases, you will want to use tasks and persist state without predefining a navigation graph. By using the OpenNavigator class, you give controllers the ability to navigate to any view by name. The open navigator validates that the requested view name exists and asks the view manager to activate it.

The OpenNavigator class derives from the Navigator class to coordinate the navigation between views and provide functionality for open navigators. You can create and begin an open navigator by calling the StartOpenNavigationTask method on the UIP manager, and passing the name of the open navigator in the configuration file as a parameter, as well as the first view and any task information if the navigator is reloading a task. For more information, see "Starting and Resuming Tasks with the Open Navigator" in Chapter 3, "Developing Applications with the UIP Application Block." Controllers can then navigate to other views by using the Navigate method and passing the view name. The navigator is responsible for validating that the view exists. As with the graph navigator, the open navigator loads information from the UIP configuration file. It uses the default state type, default view manager, and provided start view information to activate the first view.

User Controls Navigator

Windows Forms applications can have user controls that appear as child controls on a form or other user control. The UIP Application Block uses the UserControlsNavigator class to provide a navigation mechanism that shifts focus from one control to another within a form, instead of transitioning between forms. This class allows you to populate a form with user controls that have their own model and controller, and it allows you to switch between the controls by name.

To give you a better idea of how a user controls navigator operates, suppose an application has a list view on the left and a tab control with multiple tabs on the right. Each form of the tab control contains one or more controls. As the user clicks an item in the left view, it may trigger one of the tabs to become the active page. Figure 2.3 shows a form that contains user controls, and demonstrates the relationship between the views, controllers, and state. The list view on the left and the tabs on the right each have their own controller, but they communicate with the same State object.

Ff650820.uipc0203(en-us,PandP.10).gif

Figure 2.3: Windows Form with user controls

User controls de-emphasize the notion of process across time and emphasize the idea of many views collaborating to expose or retrieve information from the user without any specific sequencing. The views or controllers may raise events that are listened to by other controls. All of the views have access to the shared state of the navigator.

The UserControlsNavigator class derives from the Navigator class to coordinate the navigation between views and provide functionality for user controls navigators. You can create and begin a user controls navigator by calling the StartUserControlsTask method on the UIP manager and passing the name of the user controls navigator in the configuration file and any task information if the navigator is reloading a task. For more information, see "Starting and Resuming Tasks with the User Controls Navigator" in Chapter 3, "Developing Applications with the UIP Application Block." The controller then tells the user controls navigator which view it should transition to by calling the Navigate method and passing the name of the control or view as a parameter. All collaborating views are declared in the <userControls> section of the configuration file. This section contains a list of the forms that participate in the task. Each form can have a list of child views.

Wizard Navigator

Wizards are commonly used in Windows-based applications, and navigation occurs between the forms in a predictable way. The UIP Application Block uses the wizard navigator to provide a navigation mechanism between the forms of a wizard. You can use the wizard navigator to transition between views defined by the Cancel, Back, Next, and Finish transitions, or you can use a navigation graph to create more elaborate transitions.

Figure 2.4 shows an example wizard and demonstrates the relationship between the views, the controllers, and state. Each view has its own controller and each controller communicates with the same State object.

Ff650820.uipc0204(en-us,PandP.10).gif

Figure 2.4: Wizard example

The WizardNavigator class derives from the GraphNavigator class to coordinate the navigation between views and provide functionality for wizard navigators.

You can create and begin a wizard navigator by calling the StartNavigationTask method on the UIP manager and passing the name of the wizard in the configuration file. The wizard navigator loads information from either the <uipWizard> element or the <navigationGraph> element in the UIP configuration file, passed as a parameter to the StartNavigationTask method. To define a wizard with no branching capabilities, you define the <uipWizard> section of the configuration file. To define a wizard with branching capabilities, you define the wizard navigator in the <navigationGraph> section and set the runInWizardMode attribute to true. For more information, see "Creating a <uipWizard> Section" and "Creating the <navigationGraph> Section" in Chapter 3, "Developing Applications with the UIP Application Block." To support custom functionality when the Cancel or Finish buttons are clicked, implement the IWizardViewTransition interface. For more information, see the section, "IWizardViewTransition," in this chapter.

View Manager

View managers are responsible for creating and activating views as requested by the navigator. In some cases, you will want to create applications that have more than one user interface. In particular, you may want to create Windows-based and Web versions of the same application. The navigator coordinates the interactions of views and controllers by creating view managers and using them to execute code specific to the application type. The management of these views generally differs depending on their type; for example, the code to display a Windows Form is distinctly different from that used to display a Web page. Because of this, different managers are needed for each type of application supported.

Each view manager implements the IViewManager interface, and you can create your own if you want, but three view managers are supplied with the block:

  • WebFormViewManager — Used for managing Web views.
  • WindowsFormViewManager — Used for managing Windows Forms views and user controls views.
  • WizardViewManager — Used for managing wizards.

The IViewManager interface defines the six methods listed in Table 2.4.

Table 2.4: IViewManager Interface Methods

MethodsDescription
ActivateViewActivates a specified view.
GetCurrentTasksReturns all tasks currently being executed.
StorePropertyStores a property of the view by task ID.
IsRequestCurrentViewChecks that the current view matches the requested view.
GetViewNameForCurrentRequestChecks the URL requested and gets the view name that corresponds with the URL.
GetActiveViewCountGets the number of active views in the manager.

Each of the view managers is discussed in more detail in the following sections.

WebFormViewManager

When a Web application is navigating between views, it must save state and display pages. The code to do this is specific to Web Forms and cannot be shared with other application types. The WebFormViewManager is used to provide the methods needed to manipulate views based on the WebFormView and to save state in the process. The WebFormViewManager implements four of the six methods defined in the IViewManager interface, as shown in Table 2.5.

Table 2.5: WebFormViewManager Methods

MethodsDescription
ActivateViewActivates the view identified in the view parameter.
GetCurrentTasksReturns an array of task GUIDs currently being executed.
IsRequestCurrentViewChecks to see that the current view as stored in the state is the view being requested
GetViewNameForCurrentRequestChecks the URL requested and gets the view name that corresponds with the URL

The ActivateView method performs a number of steps necessary to activate your Web view:

  1. The view manager loads the view settings (which tell the view manager which URL to navigate to), along with any additional information contained in the extensible configuration schema.
  2. The view manager creates a sessionMoniker object that holds a reference to the navigator. The object is stored in the ASP.NET session state with a key of the task ID.
  3. The view manager calls the Response.Redirect method from ASP.NET, which creates an instance of the Web Form.
  4. ASP.NET starts a load event, which is captured by a load event handler in UIP. The handler uses the task ID (specified as a parameter on the Response.Redirect method) to identify the session moniker object. It then asks the navigator specified in this object for the view manager and tells the view manager to continue setting up the view.
  5. The view manager creates an instance of the controller, sets it on the view, and calls the Initialize method on the view. When the method returns, ASP.NET displays the view. At this point, the user is in control rather than the application block or ASP.NET.

WindowsFormViewManager

When a Windows-based application is navigating between views, it must save state, display forms, and close forms. The code to do this is specific to Windows Forms and cannot be shared with other application types. The WindowsFormViewManager is used to provide the methods and events needed to manipulate views and manage the display of Windows Forms, and to save state in the process.

The WindowsFormViewManager implements four of the six methods defined in the IViewManager interface, as shown in Table 2.6.

Table 2.6: WindowsFormViewManager Methods

MethodsDescription
ActivateViewActivates the view identified in the view parameter.
GetCurrentTasksReturns an array of task GUIDs currently being executed.
StorePropertyStores a property of the form in the internal hash table.
GetActiveViewCountGets the number of active views in the manager.

The ActivateView method performs a number of steps to activate a Windows view:

  1. The view manager loads the view settings and any additional information contained in the extensible configuration schema. This gives the view manager the class name of the view and the controller to use.
  2. The view manager creates an instance of the controller and passes an instance of the navigator (and by extension, the state) to the controller.
  3. The view manager creates an instance of the appropriate view and sets the controller on the view.
  4. The view manager calls the Initialize method on the view. Any additional information from the view settings is passed to the Initialize method.
    • If the view is a multiple document interface (MDI) child and the IsMDIChild flag is set to true, the view manager adds the view to the MDI container.
    • If the view is a floating window, the view is added to the floating window parent. The parent and the floating window are specified in the configuration file.
    • If the view has child views, the view manager finds the child views and initializes them.
    • If the view has a layout manager, the view manager calls the LayoutControls method to position the controls on the view.
  5. The view manager calls the Show method on the WindowsFormView or WindowsFormControlView class to display the view. If the view is specified as modal, the view manager calls the ShowModal method on the WindowsFormView class to display the modal view.

The view manager is responsible for making decisions about what to do with previous views. By default, the view manager closes the previous view. If the view is marked as stayOpen and the user navigates to another view, the previous view will remain open. The user will then need to manually close the view marked as stayOpen.

If a view is specified as modal (where the parent view cannot be modified until the modal window is closed) or floating (where the parent view can be modified), the previous view becomes the parent view. It remains open but behind the child view. For more information, see "Creating the <views> Section" in Chapter 3, "Developing Applications with the UIP Application Block."

WizardViewManager

The WizardViewManager is used to provide the methods and events needed to manipulate views and manage the display of forms in a wizard, and to save state in the process. The view manager hosts and displays controls according to the wizard stage. It displays the first view as a user control, attaching the buttons to the delegates in the WizardControllerBase class. The WizardViewManager implements two of the four methods defined in the IViewManager interface, as shown in Table 2.7.

Table 2.7: WizardViewManager Methods

MethodsDescription
ActivateViewActivates the view identified in the viewName parameter.
GetCurrentTasksReturns an array of task GUIDs currently being executed.

The following steps activate your wizard:

  1. The view manager retrieves the current task from the WizardNavigator.
  2. The view manager then gets a reference to the WizardContainer for the task. The WizardContainer is responsible for controlling the flow between the different views that make up the wizard sequence.
  3. The view manager calls the ActivateView method on the WizardContainer object and passes the name of the view that is to be activated as a parameter to the WizardContainer object.
  4. The WizardContainer object ensures that the current view is pushed onto the history stack for the wizard (this allows for the transition to the previous views in a wizard). After the current view has been pushed onto the stack, the container retrieves the view that is being requested from the views that are contained within its private views collection. After the view is found, it is added into the wizard panel so that it can be prepared for the user to view it.
  5. The WizardContainer object checks if the IWizardViewTransition interface is implemented for the view loaded in the panel. If so, it will do the following:
    • It will call the methods to customize the behavior of various transitions, such as DoCancel and DoFinish.
    • It will call the WizardActivated method to notify the view that it is being activated by the WizardContainer. This method allows you to perform any processing that should occur whenever the view is activated in a wizard.

Views

Views are central components of the UIP Application Block and represent the view portion of the MVC pattern. When you use the UIP Application Block, your views must include block-specific functionality so you can control them within a process. However, this functionality should not be defined in an interface specific to a view type, because the block is designed to support multiple view types.

Views are initialized by the view manager calling the virtual Initialize method on the view. Any additional information from the <view settings> section of the configuration file is passed to the Initialize method; therefore, you must ensure that the view knows what to do with the information. The UIP Application Block gives you the ability to have view-specific attributes, such as modality and background color, stored with the view configuration information. Attributes are supported for each view, and interpreted by the view manager. The UIP Application Block will pass the <view settings> element, including any additional attributes or child elements, to the view during execution.

Note   After the view is initialized, the view is aware of the state. This allows you to add code that makes use of the existence of state, such as pulling a dataset out of the state and binding it to a control on a form.

As with view managers, the UIP Application Block provides an interface that you can implement to create views. The IView interface is a generic interface that contains required properties only and can be implemented in classes that represent the specific view types in an application. The IView interface defines the properties that any view must support to interact with the management classes of the UIP Application Block.

Three implementations of the IView interface are provided with the block:

  • WebFormView — Provides common functionality to implement views derived from the ASP.NET Page class in the System.Web.UI namespace for Web applications.
  • WindowsFormView — Provides common functionality to implement views derived from the Form class in the System.Windows.Forms namespace.
  • WindowsFormControlView — Provides common functionality to implement views derived from the UserControl class in the System.Windows.Forms namespace for handling nested views in Windows-based applications.

The IView interface defines the properties and methods shown in Table 2.8 and Table 2.9.

Table 2.8: IView Interface Properties

PropertyDescription
ControllerReturns the controller being used by the view.
ViewNameReturns the name of the view.
NavigationGraphReturns the graph navigator in which the view is defined.
NavigatorReturns the navigator in which the view is defined.
TaskIdReturns the task ID related to the view.

Table 2.9: IView Interface Methods

MethodDescription
EnableUsed to determine when a WinFormControlView object gains focus or loses focus.
InitializeUsed to pass optional arguments to the view in addition to the view settings; called after the view manager instantiates the view but before calling the Show method.

In most situations, it is best for Windows-based applications and Web applications to use the WebFormView, WindowsFormView, and WindowsFormControlView classes as base classes from which the actual views (Windows Forms, user controls, and ASP.NET pages) are derived. This approach reduces the code in your views, because much of the standard view manipulation code is included within the WebFormView, WindowsFormView, and WindowsFormControlView classes.

The Enable method is used to determine when a WinFormControlView object gains or loses focus. Suppose View A's stayOpen attribute is set to true. After the user transitions to another view, View A will remain open until it is closed by the user. You can use the Enable method to determine which view is in focus.

The Initialize method is used when implementing views with custom elements or attributes, such as background color. This method passes a ViewSettings object that can be used by the view to retrieve additional information. It is called after the view manager instantiates the view, but before calling the Show method. You implement the Initialize method when deriving from a WebFormView, WindowsFormView, or WindowsFormControlView class.

The ViewSettings class captures the configuration information for a specific view that implements the IView interface. The ViewSettings contains a number of properties including the view's controller, layout manager, and modal, floating, or stay open attributes. It also captures any custom attributes or elements defined for the view.

If you extend the view by using only additional attributes, you can access these attributes by using the CustomAttributes property. If you define additional elements that provide view configuration information, you can use the Navigator property. This returns an XPathNavigator object, which you can use to query for the appropriate information. For an example, see "Adding Extensible Configuration Schema," in Chapter 3, "Developing Applications with the UIP Application Block."

Note   If you want to create your own custom view types, you will need to implement the IView interface directly. For more details on how to do this, see Appendix A, "Extending the UIP Application Block."

It is useful to examine in turn each of the three implementations of the IView interface that are provided with the block. The next sections describe these implementations.

WebFormView

You can use the WebFormView class as a base class for views in a Web application. It implements the IView interface defined in the UIP Application Block and derives from the Page class in the .NET Framework. The constructor is used to link the Load event of the Web page to a method defined within the class. You can use the WebFormView class to create your Web page views. However, if you are already inheriting a base class in your view class, you cannot also derive from WebFormView. In this situation, you must directly implement the IView interface in your class.

The WebFormView class implements the four read-only properties defined in the IView interface, as shown in Table 2.10.

Table 2.10: WebFormView Class Properties

PropertyDescription
ControllerReturns the controller being used by the page.
ViewNameReturns the name of the page.
NavigatorReturns the name of the navigator in which the page is defined.
TaskIdReturns the task ID related to the page.

Unlike Windows Forms, Web pages cannot be instantiated by UIP directly; therefore, the controller cannot be set on the view during construction. Instead, the load event handler responds to the load event started by ASP.NET, and retrieves the navigator stored in the session object. You then use the navigator to find the controller for this view, and finish initializing the view.

WindowsFormView

You can use the WindowsFormView class as a base class for views in a Windows Forms application. It implements the IView interface defined in the UIP Application Block and derives from the Form class in the .NET Framework. The constructor is used to link the Load event of the Windows Form to a method within the class. Using the WindowsFormView class allows you to create Windows Forms views, but if you are already inheriting a base class in your view class, you cannot also derive from WindowsFormView. In this situation, you must directly implement the IView interface in your class.

The WindowsFormView class implements the four read-only properties defined in the IView interface, as shown in Table 2.11.

Table 2.11: WindowsFormView Class Properties

PropertyDescription
ControllerReturns the controller being used by the form.
ViewNameReturns the name of the form.
NavigatorReturns the name of the navigator in which the form is defined.
TaskIdReturns the task ID related to the form.

WindowsFormControlView

You can use the WindowsFormControlView class as a base class for views that frequently reuse common controls in a Windows Forms application. It implements the IView interface defined in the UIP Application Block and derives from the UserControl class in the .NET Framework. The UserControl class provides the functionality of a container control and also provides the Load event. The constructor is used to link the Load event of the UserControl class to a method within the class. Using the WindowsFormControlView allows you to create user control or wizard views; however, if you are already inheriting a base class in your view class, you cannot also derive from WindowsFormControlView. In this situation, you must directly implement the IView interface in your class.

The WindowsFormControlView class implements the four read-only properties defined in the IView interface, as shown in Table 2.12.

Table 2.12: WindowsFormControlView Class Properties

PropertyDescription
ControllerReturns the controller being used by the form.
ViewNameReturns the name of the form.
NavigatorReturns the name of the navigator in which the form is defined.
TaskIdReturns the task ID related to the form.

Controller Base

A central part of the UIP Application Block is the controller base. It is equivalent to the controller portion of the MVC pattern, and its primary purpose is to control the navigation between views and act as a facade between the user interface layer and the business layer. It has access to the state for a particular task and has the ability to move through the views defined by the appropriate navigator. It also provides access to the applications underlying business components.

ControllerBase is an abstract class that you must inherit from so you can coordinate tasks and create your own controller base. However, the UIP Application Block provides only the base functionality for the controller base. You must add methods specific to your implementation that provide access to the business layer of your application and that respond to user actions by calling the appropriate methods on the navigator. Code in the controller must understand the difference between the open navigator and the graph navigator so that it can determine if it is navigating based on view names or node names. The NavigateValue passed to the Navigate method defines the next view or node to which the navigator will transition.

The ControllerBase class contains two read-only properties, as shown in Table 2.13.

Table 2.13: ControllerBase Class Properties

PropertyDescription
StateProvides access to the state associated with this controller.
NavigatorProvides the navigator for the current controller.

The ControllerBase class contains four methods, as shown in Table 2.14.

Table 2.14: ControllerBase Class Methods

MethodsDescription
EnterTaskEnables controllers to access state passed between tasks.
NavigateCalls the Navigate method on the appropriate navigator, and passes the NavigateValue as a parameter.
SuspendTaskSuspends the current task; clears the state of a suspended task from memory.
OnStartTaskNavigates to another task.
OnCompleteTaskEnds the current task; clears the state of a completed task from memory and from the state persistence provider.
Note   A task ended with the OnCompleteTask method cannot be restarted because this method removes the state from the state persistence provider. If you want to reload a task, use the SuspendTask method.

State

State represents the model portion of the MVC pattern. You use state to store the status of a task throughout a user process. State also contains methods that allow you to retrieve specific items within the state information, store the state in a persistent location, and notify views that the state has changed. The controller and view manager must have some way of knowing where the user is within the process and where the user should go next, as well as having somewhere to store ephemeral application information, for example, shopping cart contents. Also, if the user suspends a task and then restarts it, the application must have some way of retrieving their restart location and any other information it requires.

Dealing with the state related to a task presents a number of problems:

  • You must be able to access state for a task throughout the duration of that task. This state is unique to a particular task, and as such, should only be accessible to that task and the classes working with it.
  • You must be able to persist state to a permanent data store. The code that does this will vary according to the type of permanent store being used; however, the state class must be able to communicate with any type of permanent store.
  • You must be able to serialize state before persisting it, as some storage mediums require it.
  • You must be able to notify views that the state has changed, because the views in an application present the state to the user.

Each of these problems is solved in the design of the State class:

  • Instances of the State class cannot be shared across multiple sessions in a Web application. This ensures that only the task to which the state belongs can access it.
  • The State class accepts an instance of a state persistence class. This means that the state can then call methods in the particular state persistence class to store itself in a durable medium.
  • The State class implements the ISerializable interface, which facilitates serialization.
  • The State class has an event called StateChanged, to which views can subscribe to be notified of changes to the state.
    Note   It is difficult to ensure that the StateChanged event is always executed. For example, if you are storing information in a struct within the State object's internal hash table, your State class will not be aware of the contents of that struct changing, so it will not raise the event. To avoid this issue, you can derive your own strongly typed state class and raise the event whenever any state item changes. For more information, see Appendix A, "Extending the UIP Application Block."

The class contains a number of properties that allow you direct access to the state stored within it, as shown in Table 2.15.

Table 2.15: State Class Properties

PropertyDescription
CurrentViewReturns the navigator's current view.
NavigateValueReturns the next view in the navigator.
NavigatorReturns the navigator.
TaskIdReturns the current task ID.
SyncRootUsed to synchronize access to the inner hash table.

The State class contains the methods shown in Table 2.16.

Table 2.16: State Class Methods

MethodsDescription
AddAdds information to an existing instance.
RemoveRemoves information from an existing instance.
ContainsChecks whether an item exists.
AcceptPasses an instance of the state persistence provider to the existing State instance.
SaveCalls the Save method of the relevant state persistence provider class.
CopyToCopies the contents of the State object to an array.

Your views may need to be notified when state changes; therefore, the State class includes a StateChanged event to which views can subscribe. This is a feature that notifies registered listeners when changes to the State object occur. This is useful, for example, in a view that populates its controls based on information stored in the State object. The view can listen to the StateChanged event and update the contents of its controls based on changes to values stored in the State object. For an example of an application that uses the StateChanged event, please see the AdvancedHostDemo QuickStart. For more information about using the StateChanged event, see the section, "Responding to Changes in State," in Chapter 3, "Developing Applications with the UIP Application Block."

State Persistence Providers

It is not only important to store state information; you must also make sure that the information is preserved where necessary. This is important for two reasons:

  • The user may suspend and restart the process, which means that the in-memory version of the data will be lost.
  • Items in memory can become invalid due to expiration schedules that you define.

To store state, it would be possible to add methods to the State class to persist the information using a particular storage mechanism, but this would limit the flexibility of the class, and therefore the application block. Alternatively, multiple State classes could be developed for various storage mechanisms, but this would result in code duplication and maintenance issues. The solution to the problem is to use specific classes to persist the state in a durable mechanism and to link the persistence class to the State class.

The UIP Application Block provides the IStatePersistence interface to help you create your own state persistence implementation. It defines how State and Task objects can be dehydrated and rehydrated to and from any type of storage. A state persistence provider is associated with each user interface process in the XML configuration file.

The UIP Application Block contains six implementations of the IStatePersistence interface that you can use in your applications:

  • IsolatedStoragePersistence — For tasks that need to be persisted across multiple interactions or users and stored in isolated storage.
  • SecureIsolatedStoragePersistence — For tasks that need to be persisted across multiple interactions or users and stored in isolated storage, and that contain sensitive information.
  • SqlServerPersistState — For tasks that need to be persisted across multiple interactions or users in a database.
  • SecureSqlServerPersistState — For tasks that need to be persisted across multiple interactions or users in a database, and that contain sensitive information.
  • SessionStatePersistence — For transient tasks in Web applications that have lifetime equal to or shorter than a single user's Web session.
  • MemoryStatePersistence — For transient tasks in Windows-based applications, when the task will have a lifetime shorter than the running application and is only applicable to a single user.

You can also customize the state persistence mechanisms according to your needs. You may decide to only persist the state when it changes, as opposed to storing it whenever a user navigates to a different view. This results in improved performance because data access is reduced. The most scalable option is to persist data on every round trip, but the best performing option is to only persist data when the task is ending. The default block implementation always persists the data when a user changes view.

The IStatePersistence interface defines three methods that must be implemented as shown in Table 2.17.

Table 2.17: IStatePersistence Interface Methods

MethodsDescription
InitPasses any required parameters to the class.
SaveSaves the state to a particular medium.
LoadLoads the state from a particular medium.

It is useful to look at each implementation of the IStatePersistenceInterface interface in more detail.

IsolatedStoragePersistence

For desktop applications, you may want to use isolated storage to store and retrieve the state. The IsolatedStoragePersistence class is used to store references to the task state in the isolated storage. The storage is isolated by user, application, and application domain. This allows you to store state by user and application, and it means that many applications based on UIP can run at the same time and not collide. Data stored by one user on a common machine cannot be seen by another user on the same machine. User, application domain, and application were chosen to provide as much isolation as possible on multiuser machines that may have more than one application that uses UIP.

The IsolatedStoragePersistence class implements two of the methods defined in the IStatePersistence interface, as shown in Table 2.18.

Table 2.18: IsolatedStoragePersistence Class Methods

MethodsDescription
SaveSerializes the State object and writes it to a file in isolated storage.
LoadReturns the appropriate item from the State object.

SecureIsolatedStoragePersistence

The SecureIsolatedStoragePersistence class is used to store state in, and retrieve state from, isolated storage. It differs from the IsolatedStoragePersistence class in that it encrypts the data before storing it, and decrypts the data upon retrieval.

The SecureIsolatedStoragePersistence class implements the three methods defined in the IStatePersistence interface, as shown in Table 2.19.

Table 2.19: SecureIsolatedStoragePersistence Class Methods

MethodsDescription
InitReceives a NameValueCollection parameter containing the connection string to be used to connect to the SQL Server database.
SaveSerializes and encrypts the contents of the State object, and then uses the Data Access Application Block to save the information to a SQL Server database.
LoadUses the Data Access Application Block to load the information from the SQL Server database, decrypts it, and then deserializes it into the State object.

The class also uses the internal CryptHelper class that contains two methods, Encrypt and Decrypt. These methods use the Triple Data Encryption Standard algorithms to encrypt state before it is stored in the database, and to decrypt it when it is retrieved.

SqlServerPersistState

The SqlServerPersistState class is used to store state in and retrieve state from a SQL Server database. The SqlServerPersistState class implements the three methods defined in the IStatePersistence interface, as shown in Table 2.20.

Table 2.20: SqlServerPersistState Class Methods

MethodsDescription
InitReceives a NameValueCollection parameter containing the connection string to be used to connect to the SQL Server database.
SaveSerializes the contents of the State object, and then uses the Data Access Application Block to save the information to a SQL Server database.
LoadUses the Data Access Application Block to load the information from the SQL Server database, and then deserializes it into the State object.

SecureSqlServerPersistState

The SecureSqlServerPersistState class is used to store state in and retrieve state from a SQL Server database. It differs from the SqlServerPersistState class in that it encrypts the data before storing it in the database, and decrypts the data upon retrieval. The SecureSqlServerPersistState class stores the state object in a table with three columns: the taskId (a GUID), the DateAdded (a date), and State (a blob). The taskId column is the key. The State object is serialized before it is persisted as a blob.

The SecureSqlServerPersistState class implements the three methods defined in the IStatePersistence interface as shown in Table 2.21.

Table 2.21: SecureSqlServerPersistState Class Methods

MethodsDescription
InitReceives a NameValueCollection parameter containing the connection string to be used to connect to the SQL Server database.
SaveSerializes and encrypts the contents of the State object, and then uses the Data Access Application Block to save the information to a SQL Server database.
LoadUses the Data Access Application Block to load the information from the SQL Server database, decrypt the information, and then deserialize it into the State object.

The class also uses the internal CryptHelper class that contains two methods, Encrypt and Decrypt. These methods use the Triple Data Encryption Standard algorithms to encrypt state before it is stored in the database, and to decrypt it when it is retrieved.

Note   The SqlServerPersistState and SecureSqlServerPersistState classes both use the Data Access Application Block to communicate with the SQL Server database. The UIP Application Block ships with and has been tested with version 2.0 of the Data Access Application Block; however, future versions of this block may be released and they are not guaranteed to work with this version of the UIP Application Block. For more information about the Data Access Application Block, see "Data Access Application Block for .NET". For more guidance on data access, see the ".NET Data Access Architecture Guide".

MemoryStatePersistence

The MemoryStatePersistence class is used to store references to the task state in memory. There are times that it is inappropriate or undesirable to persist the state with any permanence. The MemoryStatePersistence class allows you to not persist state outside of the timeline of the current process. Typically, UIP assumes that a State object exists and that it can be persisted. By providing an in-memory persistence provider, there are no artifacts left behind after the program is shut down but UIP can still function as if the state is being persisted. The MemoryStatePersistence class stores each State object in a hash table keyed by the task ID.

Note   MemoryStatePersistence should only be used for processes in Windows-based applications that do not need to span application exits or multiple users. This is because the locking mechanisms may cause bottlenecks in busy Web applications.

The MemoryStatePersistence class implements two of the methods defined in the IStatePersistence interface, as shown in Table 2.22.

Table 2.22: MemoryStatePersistence Class Methods

MethodsDescription
SaveStores a reference to the State object in a HybridDictionary using the TaskId as a key. It synchronizes access to the dictionary to provide multiple reader single writer access.
LoadReturns the appropriate item from the HybridDictionary.
Note   Unlike the SqlServerPersistState and SecureSqlServerPersistState implementations, the MemoryStatePersistence implementation does not serialize the State object, but instead stores a reference to the object. If you have written code to store complex object interrelationships in your state object, you may observe different behavior between this state persistence provider and the SQL Server state persistence providers.

SessionStatePersistence

The SessionStatePersistence class is used to store references to the task state in the Web session state. The exact physical location of the session state is determined by setting the Mode attribute of the Session object. The valid values for this attribute are InProc, SQLServer, and StateServer. The InProc setting should be used for processes in Web applications that do not need to span application exits or multiple users. For more information about the Mode attribute, see the .NET Framework documentation.

Note   The SessionStatePersistence class should only be used in Web applications.

The SessionStatePersistence class implements two of the methods defined in the IStatePersistence interface, as shown in Table 2.23.

Table 2.23: SessionStatePersistence Class Methods.

MethodsDescription
SaveStores a reference to the state object in the Session object of the current HTTP context, using the taskId property as a key.
LoadReturns the appropriate item from the Session object.
Note   You should test your custom State types with this state persistence provider to make sure the serialization works as expected.

Additional Interfaces

This section describes additional interfaces supplied with the UIP Application Block that you may choose to implement.

ITask

When you start a task in the UIP Application Block, you have two choices. The most straightforward approach is to let the UIP Application Block manage and maintain your task IDs. This makes use of the overloaded methods on the UIP manager to start a task and the navigator will create and manage the task IDs. The disadvantage to this approach is that the block does not give you easy access to the task IDs.

If you want to suspend a task associated with the user and have the task restart with the correct state when the user is ready to resume, you will need to keep track of the task ID. To do this, you will need to implement the ITask interface from a Task class that you create. The navigator will pass the taskId property to your Task class through the Create method. You can then store the task ID; for example, by user name. The main advantage of predefining a task in this way is that you can correlate a task with a user. The Store QuickStart shows how to suspend and resume a task.

A user may work on multiple tasks at any one time; for example, a user could have two browser windows open, log in twice, and work on two different tasks. It is the responsibility of the calling application to detect this scenario and handle assigning a unique task ID to each task.

The ITask interface defines two methods as shown in Table 2.24.

Table 2.24: ITask Interface Methods

MethodsDescription
CreateCreates and stores a task/user correlation with a known Task ID.
GetReturns the Task ID.

ILayoutManager

The ILayoutManager interface gives you the ability to add custom layout logic to views in your applications. You can define generic layouts such as horizontal or vertical layouts in which your controls appear from left to right or top to bottom respectively. You can also customize a layout for each of your views by specifying the position of each control. You create a class that implements the ILayoutManager interface and defines the LayoutControls method as shown in Table 2.25.

Table 2.25: ILayoutManager Interface Methods

MethodsDescription
LayoutControlsPerforms layout functions on any child controls of the parent control. It accepts a parameter named parentControl, which is the container on which it will perform the layout.

The layout manager and the views using the layout manager must also be specified in the configuration file. For more information, see "Customizing View Layouts" in Chapter 3, "Developing Applications with the UIP Application Block."

IShutdownUIP

In Windows-based applications, a user interface process is completed when the user closes the forms involved. Even though the process is completed, control does not automatically return to the originating form. It is possible to explicitly exit the application from UIP, but if the application has additional tasks to complete, this option is not acceptable. If control is to be returned to the originating form (or to another part of the application that is not UIP-related), the classes that need to be notified when UIP is complete must implement the IShutdownUIP interface. The IShutdownUIP interface has one public method named Shutdown as shown in Table 2.26.

Table 2.26: IShutdownUIP Interface Methods

MethodsDescription
ShutdownCalled when UIP shuts down.

The classes implementing the IShutdownUIP interface must also be registered with the UIPManager class. For more details, see "UIP Shutdown" in Chapter 3, "Developing Applications with the UIP Application Block."

IWizardViewTransition

Implement the IWizardViewTransition interface if you want to customize the functionality of your wizard views. This interface provides seven methods for wizard transitions, as shown in Table 2.27.

Table 2.27: IWizardViewTransition Interface Methods

MethodDescription
DoNextPerforms custom processing before navigating to the next view.
DoBackPerforms custom processing before navigating to previous view.
DoCancelPerforms custom processing canceling the wizard task.
DoFinishPerforms custom processing before finishing the wizard task.
SupportsCancelIndicates the particular wizard view supports the cancel behavior.
SupportsFinishIndicates the particular wizard view supports the finish behavior.
WizardActivatedCalled when a wizard view is activated. Allows you to perform any processing that should occur whenever the view is activated in a wizard.

Conclusion

This chapter examined the architecture of the UIP Application Block. It explained how views are displayed, transitions occur, and state is maintained. It also examined in detail each of the elements that make up the block. By understanding the design of the UIP Application Block, you can determine how to use it in your own environment.

Start | Previous | Next

patterns & practices Developer Center

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.

Show:
© 2014 Microsoft. All rights reserved.