So let’s about MPC and how its pieces work together to create an application.

MPC is based mostly on a containment model since most user interfaces are built using containment models.  In Figure 1 you will find a simple high level diagram representing the different layers of MPC.  The top most layer is a control and in most applications the control would be a templated user control.   A presenter or multiple presenters would be contained in the content template of the user control.  Each presenter would contain a single controller and that controller would contain any models, one or more states, and any state transitions.  States would contain a single state template, and zero, one or more state actions.

clip_image002

Figure 1

 Figure 2 is XAML from the PollingItemControl.xaml file found in the Source Code & Examples.zip download.

Code Snippet
  1. <UserControl x:Class="Ops.Mpc.ExampleApplication.Polling.Controls.PollingItemControl"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6.     xmlns:presenters="clr-namespace:Ops.Mpc.Presenters;assembly=Ops.Mpc"
  7.     xmlns:controllers="clr-namespace:Ops.Mpc.Controllers;assembly=Ops.Mpc"   
  8.     xmlns:states="clr-namespace:Ops.Mpc.States;assembly=Ops.Mpc"   
  9.     xmlns:pollingitemmodels="clr-namespace:Ops.Mpc.ExampleApplication.Polling.Controls.Models"
  10.     xmlns:pollingitemsactions="clr-namespace:Ops.Mpc.ExampleApplication.Polling.Controls.Actions"          
  11.     mc:Ignorable="d"
  12.     d:DesignHeight="300" d:DesignWidth="400">
  13.  
  14.      <Border BorderBrush="DarkBlue" BorderThickness="1" Height="150" Width="150" CornerRadius="10" >
  15.          <Border.Clip>
  16.              <RectangleGeometry Rect="0,0,150,150"/>
  17.          </Border.Clip>
  18.          <presenters:Presenter x:Name="Presenter1" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch">
  19.              <controllers:Controller>
  20.                 <controllers:Controller.StateTransitions>
  21.                     <states:StateTransition From="StoppedState" To="PollingState" Transition="Up" />
  22.                     <states:StateTransition To="StoppedState" From="PollingState" Transition="Down" />
  23.                 </controllers:Controller.StateTransitions>
  24.                 <controllers:Controller.Models>
  25.                     <pollingitemmodels:PollingItemModel ItemName="PollingItemModel"/>
  26.                 </controllers:Controller.Models>
  27.                 <controllers:Controller.States>
  28.                     <states:State ItemName="StoppedState" AutoRun="True" >
  29.                         <states:StateTemplate>
  30.                             <HyperlinkButton Content="{Binding Models[PollingItemModel].Name,StringFormat='Start {0}'}" Command="{Binding StateActions[StartStateAction]}" VerticalAlignment="Center" HorizontalAlignment="Center" />
  31.                         </states:StateTemplate>
  32.                         <states:State.StateActions>
  33.                             <pollingitemsactions:InitializationStateAction ItemName="InitializationStateAction" />
  34.                             <states:NoOperationStateAction ItemName="StartStateAction" NextStateItemName="PollingState" />
  35.                         </states:State.StateActions>
  36.                     </states:State>
  37.                     <states:State ItemName="PollingState" >
  38.                         <states:StateTemplate>
  39.                             <Grid>
  40.                                 <TextBlock Foreground="Blue" Text="{Binding Models[PollingItemModel].Count}" HorizontalAlignment="Center" VerticalAlignment="Center" />
  41.                                 <HyperlinkButton Content="{Binding Models[PollingItemModel].Name,StringFormat='Stop {0}'}" Command="{Binding StateActions[StopStateAction]}" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="5"/>
  42.                             </Grid>
  43.                         </states:StateTemplate>
  44.                         <states:State.StateActions>
  45.                             <pollingitemsactions:PollStateAction ItemName="PollStateAction" StartTimeSeconds="1" PollTimeIntervalSeconds="1"/>
  46.                             <states:NoOperationStateAction ItemName="StopStateAction" NextStateItemName="StoppedState" />
  47.                         </states:State.StateActions>
  48.                     </states:State>
  49.                 </controllers:Controller.States>
  50.             </controllers:Controller>
  51.         </presenters:Presenter>
  52.     </Border>
  53. </UserControl>

Figure 2

 

The PollingItemControl is a very simple control used to demonstrate using a state action and its built in timer to create an automatically updating user interface. In this XAML you will see that there is one presenter contained within a border element. Since a presenter inherits from content control, it has some of the same available attributes like VeriticalContentAlignment and HorizontalContentAlignement. The major difference between the content control and presenter is that the default content property for a presenter is Controller. Instead of creating a single content template you can create one or more state templates, each representing a different visual state.

What is the difference between a state in MPC and a state in Silverlight/WPF visual state manager? The visual state manager lets programmers define storyboards that modify the properties of controls over a given time frame.  In order to have two different visual presentation for a control, the developer must create both sets of child controls and alter their visibility via the visual state manager, this can become messy and difficult to manage depending on the situation.  In MPC, the presenter uses totally different state templates to control the visual presentation of a state.  Along with distinct state templates, the presenter also has a distinct set of state actions that are made available when the presenter is in that state.  In Figure 2 you will find that the presenter has two states defined, StoppedSstate and PollingState.  Each of these states also define two available state actions and a hyperlink button in its template whose command is bound to one of the state actions.  Instead of using a long list of visual states in a visual state manager and mixing together animations with application flow, we can use MPC presenter states to represent the application flow and leave the visual state manager to do animations.

Binding models and commands is easier in MPC.  The root control in a state template automatically has its DataContext property set to the instance of the containing controller.  The controller exposes properties that can be bound to.  Two such properties are Model and StateActions, both of which have string indexes.  To bind a hyperlink button to a state action, like in Figure 2 line 41, all you need to do is reference the controllers StateAction property using the ItemName of the state action.

 Command="{Binding StateActions[StopStateAction]}"

You can also bind data in a similar way using the Models property and the ItemName of the model you wish to bind to.

Content="{Binding Models[PollingItemModel].Name,StringFormat='Stop {0}'}"

MPC uses a containment model to define how long models and state actions live or are available.  It also uses containment when it is trying to resolve the item name of a state action or model.  In the above code snippet example, if PollingItemModel was not resolved to the containing controller, the controller would look up the visual tree to see if there was a parent presenter and controller.  If a parent controller was found, it would ask the parent to resolve the models item name.  If the parent could not find the reference item name, it would also ask its parent and so on.  The resolution method is also used for state actions.  This allows child controls to bind to its parents models and state actions.  The life cycle of models and state actions are also controlled by containment.

Picture1

Figure 3

 

To be continued….

 

 

Last edited Apr 25, 2011 at 7:09 PM by solb10, version 9

Comments

No comments yet.