Porting the Legacy
   Application to
 MVVM/Composite
Application Guidance

           By Don Burnett
Definitions
•   Model: The underlying business entities that represent the data in your
    system.
•   View: The user int...
Advantages
•   CAL (Composite Application Library) allows modules to be individually developed, tested, and
    deployed b...
Ficticious Legacy Application Scenario
• We are working at a life insurance office and
  the application lets us look at o...
First Step
• Create the Bootstrapper
• Added references to the following Prism assemblies in
  my main (shell) project:
  ...
My Bootstrapper
public class MyApplicationBootstrapper :
  UnityBootstrapper { protected override
  DependencyObject Creat...
First Step Continued..
• Removed the StartupUri property from App.xaml. Note
  if you design in Expression Blend this will...
Next Steps
• The application runs as it did before but now
  it uses a Bootstrapper. No benefits yet, but it
  works.
• Ne...
Application Structure Overview
•   Our pretend legacy application consists primarily of a WPF user interface,
    a WCF se...
Moving Forward
• Let’s focus on the Policy aspects of the
  application.
• next step create a Policy module containing
  t...
Creating a Policy Module
• Each of these classes implements an interface,
  which enables me to easily mock these
  implem...
Adding Definition
• In the application's shell, the existing user control
  was removed and replaced with the following
  ...
Policy Controller Details
• The PolicyController class retrieves the relevant region that is
  the destination of the View...
Policy Controller Continued..
•   The Run method of the PolicyController is called in the Initialize method of the PolicyM...
Let’s Review the Pattern
Modules and Services
•     in a composite application built using the CAL, the bulk of the application logic lives in the ...
Updates
•   CAL includes a Region class that is basically a handle that wraps these locations
    together.
•    The Regio...
Regions and Registration
•   Thanks to the rich template support in WPF, you can actually add models directly to the
    r...
Region Adapters
•   ItemsControlRegionAdapter- How the adapter itself is implemented depends
    completely on the type of...
More Region Adapters
•   Once the region has been defined, it can be accessed from any class within the application by
   ...
Local Regions
• There is only one RegionManager instance in your application,
  thereby making every region globally scope...
Injection
•   The UI Composition quickstart included with the guidance illustrates this employee scenario.
     –   http:/...
More Injection
•   The region is rendered as a TabControl and contains both static and dynamic content. The General and Lo...
Benefits
•   Using local regions provides an additional benefit even if you are not using instance regions.
•   You can us...
Using Models (Code) Instead
•   Another approach is to use models. WPF will allow you to bind any model to the UI and then...
A Details View (in XAML)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:...
A Details View Detailed
•   Did you notice the details view we just looked at is one big template inside a
    resource di...
UI: Presentation Model and
           Supervising Controller
• The Presentation Model pattern assumes a model that
  conta...
Communication Challenges
•   The model is the data; it is more often than not a business object. The view is a UIElement t...
And More Challenges..
•   One of the challenges that arise when implementing separated presentation is the
    communicati...
Icommand and Delgate-Command to
              the Rescue
• WPF provides the ICommand interface. This will bind to any
  co...
Using a Delegate Command in the
         Accounts Watchlist
• WatchListService uses this command for
  adding items to the...
Publish and Subscribe
• In addition to routing commands between the view
  and a presenter or presentation model, there ar...
Events
•   To support this functionality, the CAL has an EventAggregator service that is registered with the
    container...
Event Aggregation
• In our app, the EventAggregator should be
  used for broadcasting whenever a policy item
  or an accou...
Defining an Event
•    The event is defined in our application’s infrastructure assembly, to which all modules in our
    ...
Composite Extensions to support
       Non-UI Elements and processes
•   Brian Noyes’ Composite Extensions: If you like th...
No More Code Behind
• ViewModels
More Tools- Calcium

• Introduction
• Calcium is a WPF composite application toolset that
  leverages the Composite Applic...
Calcium Additions
Calcium Features
•   Duplex messaging services for interacting with the user from the client or
    server using the same ...
Calcium
•   Calcium is a WPF composite application toolset that leverages the Composite
    Application Library. It provid...
Porting the Legacy
   Application to
 MVVM/Composite
Application Guidance

           By Don Burnett
Upcoming SlideShare
Loading in...5
×

Porting the Legacy Application to Composite Application Guidance

1,543

Published on

Porting the Legacy Application to Composite Application Guidance

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,543
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
3
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Porting the Legacy Application to Composite Application Guidance

  1. 1. Porting the Legacy Application to MVVM/Composite Application Guidance By Don Burnett
  2. 2. Definitions • Model: The underlying business entities that represent the data in your system. • View: The user interface representation of the underlying Model). • Presenter: When the Model can provide the data that the View requires without any complex manipulation or transformation, then the View binds directly to the Model and the Presenter handles the state of the View in the cases where complex user interface logic is required, such as changing colours of controls and showing/hiding controls • PresentationModel: When the View cannot bind directly to the Model, a PresentationModel class is used to provide the Model in a format more easily consumed by the View acting as a façade. The PresentationModel class also manages UI-specific state and behaviour. • Controller: Controller classes to manage the interaction between multiple views.
  3. 3. Advantages • CAL (Composite Application Library) allows modules to be individually developed, tested, and deployed by different individuals or sub-teams; they also allow them to be modified or extended with new functionality more easily, thereby allowing the application to be more easily extended and maintained. Note that even single-person projects experience benefits in creating more testable and maintainable applications using the composite approach. • Provide a common shell composed of UI components contributed from various modules that interact in a loosely coupled way. This reduces the contention that arises from multiple developers adding new functionality to the UI, and it promotes a common appearance. • Promote re-use and a clean separation of concerns between the application's horizontal capabilities, such as logging and authentication, and the vertical capabilities, such as business functionality that is specific to your application. • Help maintain a separation of roles by allowing different individuals or sub-teams to focus on a specific task or piece of functionality according to their focus or expertise. Provide a cleaner separation between the user interface and the business logic of the application • Doing all of this this means the UI designer can focus on creating a richer user experience. • Composite applications are highly suited to a range of client application scenarios. For example, a composite application is ideal for creating a rich end-user experience over a number of disparate back-end systems.
  4. 4. Ficticious Legacy Application Scenario • We are working at a life insurance office and the application lets us look at our client’s life insurance policies. • It was done in Winforms and has since been moved to WPF, but still uses code behinds. • It is inefficient to scale as they have a growing number of customers and branch offices.
  5. 5. First Step • Create the Bootstrapper • Added references to the following Prism assemblies in my main (shell) project: – Microsoft.Practices.Composite.dll – Microsoft.Practices.Composite.Wpf.dll – Microsoft.Practices.UnityExceptions.dll – Microsoft.Practices.Unit.dll – Microsoft.Practices.ObjectBuilder.dll • Added a new class called MyApplicationBootstrapper, which inherits from UnityBootstrapper as shown in the following code example.
  6. 6. My Bootstrapper public class MyApplicationBootstrapper : UnityBootstrapper { protected override DependencyObject CreateShell() { MainWindow window = new MainWindow(); window.Show(); return window; } protected override IModuleEnumerator GetModuleEnumerator() { return new StaticModuleEnumerator(); } }
  7. 7. First Step Continued.. • Removed the StartupUri property from App.xaml. Note if you design in Expression Blend this will automatically get added to App.xaml, you have to keep removing it if you notice it showing up again. • Created an instance of in the Application.Startup event handler as shown in the following code example. private void Application_Startup(object sender, StartupEventArgs e) { MyApplicationBootstrapper bootstrapper = new MyApplicationBootstrapper(); bootstrapper.Run(); }
  8. 8. Next Steps • The application runs as it did before but now it uses a Bootstrapper. No benefits yet, but it works. • Next step, start writing some tests and a some modules to contain the existing UI controls as views in a more Prism-like approach.
  9. 9. Application Structure Overview • Our pretend legacy application consists primarily of a WPF user interface, a WCF service that provides access to a SQL Server database and a few support libraries. • One of the support libraries provides some classes that deal with the interaction between the user interface and the WCF service and is my prime candidate for making some improvements using the Prism guidance. • The plan: create Prism Modules for the project and to create the relevant Views, ViewModels, Services, and Controllers that are required to implement the functionality. Rather than having to fully re-write the underlying code that handles UI/WCF Service interaction. • Write a Prism “façade” that will simply call out to the existing infrastructure, which I can eventually replace as time progresses. This gives me the testability advantages of Prism without having to rewrite the application, which would be a costly and time consuming task.
  10. 10. Moving Forward • Let’s focus on the Policy aspects of the application. • next step create a Policy module containing the PolicyModule, a PolicyService, PolicyTreeView, PolicyTreeViewModel and a PolicyController, which will handle the interactions between the different views of a policy (when I get that far).
  11. 11. Creating a Policy Module • Each of these classes implements an interface, which enables me to easily mock these implementations to test specific aspects of the application. • At this stage implementations are very simple in that they just initialize the relevant Views, ViewModels, etc. • The View itself is simply a UserControl that contains a root Grid element with a background. The important thing is to get it loaded and displayed first.
  12. 12. Adding Definition • In the application's shell, the existing user control was removed and replaced with the following region definition. – <ContentControl x:Name="_navigation" cal:RegionManager.RegionName="{x:Static inf:RegionNames.Navigation}" DockPanel.Dock="Left" /> • The "cal" XML namespace resolves to "http://www.codeplex.com/CompositeWPF" and the "inf" XML namespace resolves to an infrastructure assembly that contains constants for the region names.
  13. 13. Policy Controller Details • The PolicyController class retrieves the relevant region that is the destination of the View and adds the View for the associated ViewModel to that region and then activates it as shown below. public void Run() { IRegion region = this._regionManager.Regions[RegionNames.Navigation]; region.Add(this._policyTreeViewModel.View); region.Activate(this._policyTreeViewModel.View); } • The call to the Activate method is essential if you want to be able to see your View. Until the Activate method is called, you will not be able to see your View.
  14. 14. Policy Controller Continued.. • The Run method of the PolicyController is called in the Initialize method of the PolicyModule after registering the required views and services, as shown in the following code example. { // NOTE: The ContainerControlledLifetimeManager ensures that the same // instance is returned by any call to Resolve or ResolveAll. this._container.RegisterType<IPolicyService, PolicyService>(new ContainerControlledLifetimeManager()); this._container.RegisterType<IPolicyController, PolicyController>(new ContainerControlledLifetimeManager()); this._container.RegisterType<IProjectTreeView, PolicyTreeView>(); this._container.RegisterType<IPolicyTreeViewModel, PolicyTreeViewModel>(); } #endregion Private Methods #region IModule Members public void Initialize() { RegisterViewsAndServices(); IPolicyController controller = this._container.Resolve<IPolicyController>(); controller.Run(); } #endregion
  15. 15. Let’s Review the Pattern
  16. 16. Modules and Services • in a composite application built using the CAL, the bulk of the application logic lives in the modules. • MessagesModule provides related messsages for each policy that is selected. • PolicyModule provides real-time information on the accounts, for the selected accounts. • AccountsModule provides a Watch Module that displays a list of accounts you are working with. • ListModule displays the list of policies in which you an account has and allows you to perform appropriate transactions. • Using a region removes the need for the module to have any specific reference to the UI or have any knowledge of how the views injected will be laid out and displayed. Special thanks to MSDN magazine for letting me re-use this cool diagram.. From their article: http://msdn.microsoft.com/en-us/magazine/cc785479.aspx
  17. 17. Updates • CAL includes a Region class that is basically a handle that wraps these locations together. • The Region class contains a Views property that is a read-only collection of the views to be displayed within the region. • Views are added to the region by calling the region's add method. • The Views property actually contains a generic collection of objects; it is not limited to containing only UIElements. • This collection implements INotifyPropertyCollectionChanged so that the UIElement associated with the region can bind to it and observe changes.
  18. 18. Regions and Registration • Thanks to the rich template support in WPF, you can actually add models directly to the region. That model can then have an associated Data-Template defined for it that will define the rendering for the model. If the item added is a UIElement or a user control, then WPF will just render it as is. This means that if you have a region that is a tab of open policies, you can sadd the PolicyModel or PolicyPresentation-Model to the region and then define a custom DataTemplate to control the display rather than having to create a custom PolicyView user control. • Regions can be registered in two ways. The first way is defined in XAML by annotating a UIElement with a RegionName attached property. • Once a region has been defined via XAML, it will automatically be registered at run time with RegionManager, one of the composition services registered by the bootstrapper. RegionManager is essentially a Dictionary where the key is the name of the region and the value is an instance of the IRegion interface. The RegionManager attached property uses a RegionAdapter to create this instance. • CAL ships with three region adapters that are registered by the bootstrapper— ContentControlRegionAdapter, ItemsControlRegionAdapter, and SelectorRegionAdapter. Adapters are registered with a RegionAdapterMappings class. Adapters all inherit from RegionAdapterBase, which implements the I-RegionAdapter interface.
  19. 19. Region Adapters • ItemsControlRegionAdapter- How the adapter itself is implemented depends completely on the type of UIElement to which it is being adapted. In ItemsControlRegionAdapter, the bulk of its implementation is in the Adapt method. • The Adapt method accepts two parameters. The first parameter is an instance of the Region class itself that Region-Manager creates. • The second parameter is the UIElement that represents the region. The Adapt method performs the relevant plumbing to ensure that the region works with the element. • In the case of an ItemsControl, the adapter automatically removes any child items from the ItemControl itself and then adds them to the region. The region's Views collection is then bound to the ItemsSource of the control. • The second method overridden is CreateRegion, which returns a new AllActiveRegion instance. • Regions can contain views that are active or inactive. In the case of the ItemsControl, all of its items are active all the time because it does not have a notion of selection. However, in the case of other types of regions, such as Selector, only one item is selected at a time. • A view can implement the IActiveAware interface so that it is notified by its region that it is selected. Whenever the view is selected, it will have its IsSelected property set to true.
  20. 20. More Region Adapters • Once the region has been defined, it can be accessed from any class within the application by grabbing hold of the Region-Manager service. • The common way to do this in a CAL application is to have the dependency injection container inject the RegionManager into the constructor of the class that needs it. To add a view or model to a region, simply call the region's Add method. When you add a view, you can pass an optional name: _regionManager.Regions["MainRegion"].Add( somePresentationModel, "SomeView"); • You can later use that name to retrieve the view from the region by using the region's GetView method.
  21. 21. Local Regions • There is only one RegionManager instance in your application, thereby making every region globally scoped. • This addresses a wide set of scenarios, but there are situations where you may want to define a region that exists only at a particular scope. • An example of where you might want to do this is when your application has a view for a account/policy where multiple instances of the view can be displayed at the same time. • If these views are fairly complex, they behave like mini-shells or CompositeViews. In these cases, you may want each view to have its own regions, as the shell does. • The CAL allows you to define a local RegionManager for a view so that any regions defined within it or its child views are automatically registered in that local region.
  22. 22. Injection • The UI Composition quickstart included with the guidance illustrates this employee scenario. – http://msdn.microsoft.com/en-us/library/dd458809.aspx • In the quickstart there is an employee list. As you click on each employee, you see the associated employee detail. • For each employee selection, a new EmployeeDetailsView is created for that employee and added to the DetailsRegion . • This view contains a local TabRegion, into which the EmployeesController injects a ProjectListView in its OnEmployeeSelected method.
  23. 23. More Injection • The region is rendered as a TabControl and contains both static and dynamic content. The General and Location tabs are statically defined within the XAML. The Current Projects tab, however, has its views injected. • You can see in the code that a new RegionManager instance is returned from the detailsRegion.Add method. Also notice that I am using the overload of Add that passes in a name for the view and sets the createRegionManagerScope parameter to true. Doing this creates a local RegionManager instance that will be used for any regions defined in the children. The TabRegion itself is defined in the XAML of the EmployeeDetailsView: <TabControl AutomationProperties.AutomationId="DetailsTabControl" cal:RegionManager.RegionName="{x:Static local:RegionNames.TabRegion}" .../>
  24. 24. Benefits • Using local regions provides an additional benefit even if you are not using instance regions. • You can use them for defining a top-level boundary so that a module does not automatically expose its regions to the rest of the world. • To do this, add the top-level view for that module into a region and specify for it to have its own scope. • Without views you would have no need for a composite. Views are the single most important element that you will build within your composite apps, as they are the gateway for your users to the world of functionality that your application provides. • Views are typically the screens of your application. Views can contain other views, thereby becoming composite views. Another use of views is for menus and toolbars. • WPF supports a much richer notion of a View than what was the convention in the Windows Forms world. In Windows Forms you were basically restricted to using controls as your visual representation. • In WPF, this model is still supported and you can create custom user controls for representing your different screens. • Views are typically the screens of your application. Views can contain other views, thereby becoming composite views. Another use of views is for menus and toolbars. In our application, for example, the ContainerBottom.xaml Toolbar is a view that contains buttons for operations that work like normal system ones such as Submit, Cancel, Submit All, and Cancel All.
  25. 25. Using Models (Code) Instead • Another approach is to use models. WPF will allow you to bind any model to the UI and then use a DataTemplate to render it. • Templates are rendered recursively, meaning that if a template renders an element that binds to a property of the model, that property will be rendered using a template if it is available. • WPF supports a much richer notion of a View than what was the convention in the Windows Forms world. In Windows Forms you were basically restricted to using controls as your visual representation. In WPF, this model is still supported and you can create custom user controls for representing your different screens. If you look throughout the CAL sample application, this is the primary mechanism employed for defining views. • Another approach is to use models. WPF will allow you to bind any model to the UI and then use a DataTemplate to render it. Templates are rendered recursively, meaning that if a template renders an element that binds to a property of the model, that property will be rendered using a template if it is available. • Everything starts with the Employee-DetailsPresentationModel. Its template declares that it should be rendered as a TabControl. As part of the template, it binds the TabControl's ItemsSource to the EmployeeDetailsPresentationModel's EmployeeDetails collection property. This collection is populated with two pieces of information when the Employee details are constructed: public EmployeesDetailsPresentationModel() { EmployeeDetails = new ObservableCollection<object>(); EmployeeDetails.Insert(0, new HeaderedEmployeeData()); EmployeeDetails.Insert(1, new EmployeeAddressMapUrl()); ...
  26. 26. A Details View (in XAML) <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:EmployeesDetailsView= "clr- namespace:ViewModelComposition.Modules.Employees.Views.EmployeesDetailsView"> <DataTemplate DataType="{x:Type EmployeesDetailsView:HeaderedEmployeeData}"> <Grid x:Name="GeneralGrid"> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition Width="5"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <TextBlock Text="First Name:" Grid.Column="0" Grid.Row="0"> </TextBlock> <TextBlock Text="Last Name:" Grid.Column="2" Grid.Row="0"> </TextBlock> <TextBlock Text="Phone:" Grid.Column="0" Grid.Row="2"></TextBlock> <TextBlock Text="Email:" Grid.Column="2" Grid.Row="2"></TextBlock> <TextBox x:Name="FirstNameTextBox" Text="{Binding Path=Employee.FirstName}" Grid.Column="0" Grid.Row="1"></TextBox> <TextBox x:Name="LastNameTextBox" Text="{Binding Path=Employee.LastName}" Grid.Column="2" Grid.Row="1"></TextBox> <TextBox x:Name="PhoneTextBox" Text="{Binding Path=Employee.Phone}" Grid.Column="0" Grid.Row="3"></TextBox> <TextBox x:Name="EmailTextBox" Text="{Binding Path=Employee.Email}" Grid.Column="2" Grid.Row="3"></TextBox> </Grid> </DataTemplate> <DataTemplate DataType="{x:Type EmployeesDetailsView:EmployeeAddressMapUrl}"> <Frame Source="{Binding AddressMapUrl}" Height="300"></Frame> </DataTemplate> <DataTemplate DataType="{x:Type EmployeesDetailsView:EmployeesDetailsPresentationModel}"> <TabControl x:Name="DetailsTabControl" ItemsSource="{Binding EmployeeDetails}" > <TabControl.ItemContainerStyle> <Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource RoundedTabItem}"> <Setter Property="Header" Value="{Binding HeaderInfo}" /> </Style> </TabControl.ItemContainerStyle> </TabControl> </DataTemplate> </ResourceDictionary>
  27. 27. A Details View Detailed • Did you notice the details view we just looked at is one big template inside a resource dictionary?? • In the sample, A separate tab will be rendered for each item in the collection. As the first item gets rendered, WPF will use the DataTemplate specified for HeaderedEmployeeData. • The HeaderedEmployeeData model contains the employee name and contact info. Its associated template renders the model as a series of labels for displaying the information. • The second item will get rendered using the template specified for EmployeeAddressMapUrl, which in this case will render a frame that contains a Web page with a map of where the employee lives. • What’s new here is that a view as you previously knew it only existed at run time through the combination of the model and its associated template. You can also implement a hybrid of both approaches, where you have user controls that have controls within them that are then bound to models that are rendered through templates.
  28. 28. UI: Presentation Model and Supervising Controller • The Presentation Model pattern assumes a model that contains both the behavior and the data for the UI. The view then projects the presentation model's state "onto the glass." • Behind the scenes the model interacts with business and domain models. The model also includes additional state information such as the selected item or whether an element is checked. The view then binds to the Presentation Model directly and renders it. • The rich support in WPF for data binding, templates, and commands makes the Presentation Model pattern almost a nuclear option for development with anything else.
  29. 29. Communication Challenges • The model is the data; it is more often than not a business object. The view is a UIElement to which the model directly binds. And lastly, the presenter is a class that contains the UI logic. In this pattern, the view contains very little logic other than delegating to the presenter and responding to callbacks from the presenter to perform simple actions including either displaying or hiding a control. • One of the challenges that arise when implementing separated presentation is the communication between the view and the presentation model or presenter. There are several approaches to handling this. • One often implemented is having event handlers in the view that either directly call or raise events to the presentation model or presenter. The same UIElements that initiate calls to the presenter often have to be enabled or disabled in the UI based on state changes or permissions. This requires the view to have methods that can be used to call it back in order to disable those elements.
  30. 30. And More Challenges.. • One of the challenges that arise when implementing separated presentation is the communication between the view and the presentation model or presenter. There are several approaches to handling this. • One that is often implemented is having event handlers in the view that either directly call or raise events to the presentation model or presenter. The same UIElements that initiate calls to the presenter often have to be enabled or disabled in the UI based on state changes or permissions. This requires the view to have methods that can be used to call it back in order to disable those elements. • Another approach is to use WPF commands. Commands provide a clean way of addressing these situations without requiring all the back-and-forth delegation logic. Elements in WPF can bind to commands to handle both execution logic and enabling or disabling elements. When a UIElement is bound to a command, it will automatically be disabled whenever the command's Can-Execute property is false. Commands can be bound declaratively in XAML. • WPF provides RoutedUICommands. Using these commands requires a handler for the Execute and Can-Execute methods within the view's codebehind—which means that code modification is still required for the back-and-forth communication. RoutedUICommands also have other constraints, such as requiring the receiver to be in WPF's logical tree, a constraint that is problematic for building composite applications.
  31. 31. Icommand and Delgate-Command to the Rescue • WPF provides the ICommand interface. This will bind to any command that implements it. This means you can create custom commands fullfill all of your needs, and you don't need to touch the codebehind. • The downside is that you have to implement custom commands, such as SaveCommand, Submit-Command, and CancelCommand yourself in the application. • The CAL includes new commands such as the Delegate- Command<T>,which allows you to specify the two delegates for the Execute and CanExecute methods in the constructor. • Using this command allows you to wire up views without having to delegate through methods defined in the view itself and without having to create custom commands for each action.
  32. 32. Using a Delegate Command in the Accounts Watchlist • WatchListService uses this command for adding items to the watch list public WatchListService(IMarketFeedService marketFeedService) {this.marketFeedService = marketFeedService; WatchItems = new ObservableCollection<string>(); AddWatchCommand = new DelegateCommand<string>(AddWatch); }
  33. 33. Publish and Subscribe • In addition to routing commands between the view and a presenter or presentation model, there are other types of communication, such as event publication, that need to be handled. • In these cases, the publisher is completely decoupled from the subscriber. • For example, our “legacy” application needs to have a module that exposes a Web service endpoint that receives notifications from the server. Once that notification is received, it needs to fire an event to which components within the same or other modules can subscribe.
  34. 34. Events • To support this functionality, the CAL has an EventAggregator service that is registered with the container. Using this service, which is an implementation of the Event Aggregator pattern, publishers and subscribers can communicate in a loosely coupled fashion. • The EventAggregator service contains a repository of events that are instances of the abstract EventBase class. The service has one GetEvent<TEventType> method for retrieving event instances. • The CAL includes the CompositeWPFEvent<TPayload> class that inherits EventBase and provides specific support for WPF. This class uses delegates rather than full .NET events for publishing. Under the hood it uses a DelegateReference class that, by default, functions as a weak delegate (see msdn.microsoft.com/library/ms404247). This allows subscribers to be garbage collected even when they do not explicitly unsubscribe. • The CompositeWPFEvent class contains Publish, Subscribe, and Unsubscribe methods. Each uses the generic type information of the event to ensure that the publisher passes the correct parameters (TPayload) and the Subscriber property receives them (Action<TPayload>). • The Subscribe method allows passing in a ThreadOption that can be set to PublisherThread, UIThread, or BackgroundThread. This option determines on which thread the subscribing delegate will be invoked. Also, the Subscribe method is overloaded to allow passing in a Predicate<T> filter so that the subscriber only gets notified of the event if the filter is satisfied.
  35. 35. Event Aggregation • In our app, the EventAggregator should be used for broadcasting whenever a policy item or an account is selected in the positions screen. The messages module subscribes to this event and displays messages for the account or policy. • public class AccountSelectedEvent : CompositeWpfEvent<string> { }
  36. 36. Defining an Event • The event is defined in our application’s infrastructure assembly, to which all modules in our application reference. public void Run() { this.regionManager.Regions[“MessagesRegion"].Add( articlePresentationModel.View); eventAggregator.GetEvent<AccountSelectedEvent>().Subscribe( ShowNews, ThreadOption.UIThread); } public void ShowNews(string companySymbol) { articlePresentationModel.SetAccount(companyAccount); } Another module's Controller then subscribes to this event in its Run method: private void View_CompanySymbolSelected(object sender, DataEventArgs<string> e) { _trendLinePresenter.OnCompanySymbolSelected(e.Value); EventAggregator.GetEvent<TickerSymbolSelectedEvent>().Publish( e.Value); } The presentation model then fires the event whenever an account is selected.
  37. 37. Composite Extensions to support Non-UI Elements and processes • Brian Noyes’ Composite Extensions: If you like the modularity and publish -subcribe events capabilities in Prism and would like to be able to do those same things to adapt your legacy .NET application here are some extensions and add- ons that are must haves. • These extensions allow you to use the modular loading patterns and capabilities of Prism as well as the pub/sub events in a Windows Forms application, or any other kind of application (even console apps, WCF services, etc.). • KEY ELEMENTS (staying the same): – A CompositeEvent class that has all the same capability as the CompositePresentationEvent class in Prism2, but is not tied to the WPF libraries at all. – For the UI thread dispatching capability, it uses the SynchronizationContext class (which is used under the covers by both WPF and Windows Forms, so this class will also work with WPF). – A SimpleUnityBootstrapper class that removes the tie to WPF in the bootstrapper by removing the creation of the shell and the region adapter stuff. • Check out Brian Noyes’ Downloads and Videos and Demos at DNR.TV • http://www.dnrtv.com/default.aspx?showNum=132
  38. 38. No More Code Behind • ViewModels
  39. 39. More Tools- Calcium • Introduction • Calcium is a WPF composite application toolset that leverages the Composite Application Library. It provides much of what one needs to rapidly build a multifaceted and sophisticated modular application. • Calcium consists of a client application and server based WCF services, which allow interaction and communication between clients. Out of the box, Calcium comes with a host of modules and services, and an infrastructure that is ready to use in your next application.
  40. 40. Calcium Additions
  41. 41. Calcium Features • Duplex messaging services for interacting with the user from the client or server using the same API. Interact with the user using Message Boxes from the server! • Module Manager for enabling or disabling of modules at runtime. • A User Affinity module that assists collaboration with other users of the application. • A Command Service to associate WPF ICommands with content interfaces that only become active when an active view or viewmodel implements the interface. • Region Adapters for ToolBars and Menus. • Client-server logging ready to work out-of-the-box. • Includes modules, such as a Web Browser, Text Editor, Output Window, and many more. • Tabbed interface with dirty file indication (reusable across modules).
  42. 42. Calcium • Calcium is a WPF composite application toolset that leverages the Composite Application Library. It provides much of what one needs to rapidly build a multifaceted and sophisticated modular application. Calcium consists of a client application and server based WCF services, which allow interaction and communication between clients. Out of the box, Calcium comes with a host of modules and services, and an infrastructure that is ready to use in your next application. • Get it today at: http://calcium.codeplex.com/
  43. 43. Porting the Legacy Application to MVVM/Composite Application Guidance By Don Burnett

×