MCE Patterns

MCE has various patterns for presenting views in an environment. You can build your presentation logic based on your requirements and the various patterns available in MCE. The following section discuss the various patterns available in MCE.


MCE allows association of a particular State Machine state to a view. This is a common pattern when presenting one view at a time. That is, a response would normally be made only to the view that is in focus.

To follow this pattern, create a state for a view that you need to present exclusively. In each state, place a StateInitialization handler where the ShowLogicalView activity is placed. Every time the state is entered this StateInitialization is executed and the view is either created or focused automatically. In that state, you can wait for the new view event so as to make sure that it is handled for the correct view.

A small variant of this pattern includes a StateFinalization handler that deletes the view automatically, if it does not need to be re-shown frequently.


Whenever a navigational event is received in a work unit, the view that raised that event is automatically data bound (PhysicalToLogical) upon receiving the event. It is data bound again upon idling of the workflow when the event handling is over. However only that particular view is data bound. When dealing with multiple views, the additional views will not be data bound automatically. If those additional views need to be bound, views that are other than the one which triggered the workflow, use the DataBind activity.

The DataBind activity is useful when receiving external events for which the UI needs to be updated. The bindings are not automatic and must be done explicitly.

Databinding can be a resource-heavy operation and is best kept to a necessary minimum. For the same reason, it is suggested that generic databinding be avoided on all views on every event handling.


Multiple MCE containers can exist simultaneously in a hosting environment. If all the containers are acting on behalf of different unrelated work units, there is nothing to be configured. Each container can start its own workunit and will operate according to its instructions.

Containers can also be chained in groups that will be run by a single workunit. To do this, containers need to be related to each other by way of a property RelatedContainer. This property is exposed by all MCE containers. There must always be a container with this property not set in every chain, and this container must be the root container of the chain. This root container will receive the ExternalCommands and the events related to the work unit. However any container in the chain can forward events to the contained work unit by itself.

When multiple containers are chained, a workunit will be able to either show a view in each one of them, or assign them to child workunit operation. A workunit definition declares which container it expects to work with, and a mapping can be established when starting the work unit. The establishment of the mapping can happen through some of the overloads of the StartWorkunit API on the engine. These overloads will take either a dictionary mapping that maps a host container names to workunit names or a string with the format:

ChildContainerName=ParentContainerName[;ChildContainerName=ParentContainerName;…]

This would specify the same information.


A view can contain one or more MCE containers. This can used when there further need to partition the visual space beyond that provided by the host or parent. When a physical view contains containers, these are automatically chained to the root container to which the workunit belongs so that they can join the workunit operation. However, it is not possible for workunit 1 to access nested containers in a view of workunit B, unless these are in a child-parent relationship. This limitation stems from the need to maintain control over the presentation of the container owning view.

When a nested container is declared in the logical view definition, it will be available at design time in the container combo box, in the ShowLogicalView activity and in the StartWorkunit activity. Otherwise, the name of the container must be input. To avoid confusing container names, nested containers always gets prefixed with the name of the owning view instance followed by a dot. For example, if a view PersonalDetails has two nested containers named Left and Right, their full names will be PersonalDetails.Left and PersonalDetails.Right respectively.


When a view creates a container dynamically, after its creation, that container is deemed dynamic. Since the MCE is not aware of the existence of the container, a dynamic container must be registered explicitly. To do that, call the MCEEngine API RegisterNestedContainer, and pass in the dynamic container, the name used to register it, and the owning view.

Although dynamic containers are created by a view, they need not be embedded in the view. It is possible to have a dynamic container created by a view yet not be included in the view space as in a dialog box or in a separate window. This is true if the container is controlled by the view itself and is destroyed when the view gets destroyed or it is in the same process and in the same appdomain as the owning view. MCE does not support cross process or cross appdomain operation.


Events are routed by a pluggable logic that governs the way in which this routing needs to be done for the different kinds of events in MCE such as:

  1. Navigational events, originating by a view and directed to a workflow
  2. External events, originating in a container and directed to a workflow
  3. External events, originating in a workflow and directed to one of its children or parents
  4. External Commands, originating in a workflow and directed to a container

Currently no routing is available on view commands.

The routing logic is provided by a workflow service implementing the MCE interface IRoutingService. If not customized, the default logic implemented in MCE follows the following rules:

  • Every navigational event is first routed to all the parents for interception. This happens from the top level parent to the lowest one. Each intercepting process can interrupt the flow via the InterruptEvent activity. If a specific handler for the event is found (one bound to a specific logical view instance), it will be invoked before the generic one.
  • Every ExternalCommand will flow from parent to parent until it reaches the container if the WorkunitId property is null. If it is not null, it will flow to the target child passing through all the intermediary parents in between.
  • Every ExternalEvent is routed from the container to the target workflow, passing from all the parents in hierarchical order first.

The general rule is that if an event is not handled by a work unit, the routing will continue. If it is handled but not interrupted it will continue processing.


A child workunit reuses a particular physical view across multiple processes and can reuse a full piece of UI logic among larger UI processes.

A child workunit gets created by a StartWorkunit activity and gets assigned one or more containers by the parent via container mapping. If no container mapping is provided, the child will try to access the parent containers directly with its own name, and may generate exceptions if none is found.

A child can present a view on its own, generate commands, and receive events from the external environment. The parent workunit however is able to maintain a tight control on its children:

  1. It can intercept, override and interrupt all the inflowing events (navigational and external)
  2. It can intercept and interrupt all the out-flowing commands to the environment (no provision for view commands here)
  3. It can persist and rehydrate its children using the Persist and Reload activities.
  4. By way of built in automatic events, it can receive notification of the major infrastructural conditions of each of its children.

The infrastructure events can be received via the usual HandleExternalMceEvent activity that exposes automatic infrastructure events among the possible EventName choices.

The available infrastructural events are:

  • Workunit::Started: Invoked as the child workunit gets started
  • Workunit::Completed: Invoked upon completion of a child workunit
  • Workunit::Faulted: Invoked when a child faults, includes the fault details
  • Workunit::Persisted: Invoked as a child workunit gets persisted
  • Workunit::Aborted: Invoked if a child workunit aborts
  • Workunit::Rehydrated: Invoked if a child workunit gets rehydrated
  • Workunit::Unloaded: Invoked as a child workunit gets discarded from memory
  • Workunit::Closing: Invoked when a child workunit is going to close

These events will be routed according to the Routing service logic as if they were ExternalCommands. They will be available beyond the direct parent workunit and to the container.


Show: