This is the first of several posts on my journey migrating a legacy application to use the Composite Application Guidance for WPF, which (like Brian Noyes) I prefer to call Prism, mainly because it's shorter, but it's also cooler!
I've watched the "Brian Noyes on Prism" dnr TV episode intently, read through the guidance documentation, I've done the hands-on lab, all of the quick starts and dissected and analysed the StockTraderRI
sample application, so now I figure I'm ready to start cranking some Prism code for our legacy application1.
1By "legacy", I mean that it's a regular WPF application that was not created using the Prism (or any other specific) guidance, so it's not a green field project.
Understanding the Terminology
I don't pretend to be completely clued up on all aspects of design patterns, but I'm aware of the key concepts behind Model-View-Controller (MVC) and its numerous variants, so when I opened up the StockTraderRI
sample application, I was initially a bit confused to see a combination of Presenters from Model-View-Presenter (MVP; also referred to as Supervising Controller in the guidance), Controllers from MVC, and PresentationModels from Presentation Model, or Model-View-ViewModel (MVVM) to give it its more WPF-focused name.
After a bit of digging, it was clear that the Prism team were using a mixture of approaches and for good reason (of course), which I thought I'd just quickly explain for my own recording purposes if nothing else.
- Model: The underlying business entities that represent the data in your system (pretty much standard throughout all of the MV* patterns). E.g.
StockTraderRI.Infrastructure.Models.NewsArticle
class in the StockTraderRI
sample.
- View: The user interface representation of the underlying Model (also pretty much standard throughout all of the MV* patterns). E.g.
StockTraderRI.Modules.News.Article.ArticleView
class in the StockTraderRI
sample.
- 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. E.g.
StockTraderRI.Modules.News.Article.NewsReaderPresenter
class in the StockTraderRI
sample. The NewsReader
View binds directly to properties of the NewsArticle
Model class, which is supplied by the NewsReaderPresenter
.
- 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. E.g. StockTraderRI.Modules.News.Article.ArticlePresentationModel
class in the StockTraderRI
sample. The ArticleView
class binds Articles
property exposed by the ArticlePresentationModel
class.
Note: Given that MVVM is a WPF-specific variation of Martin Fowler's Presentation Model pattern, I prefer the term ViewModel
to PresentationModel
; if nothing else, it's shorter. :)
- Controller: The
StockTraderRI
sample application uses Controller
classes to manage the interaction between multiple views. E.g. StockTraderRI.Modules.News.Controllers.NewsController
class, which manages interactions between the ArticleView
and the NewsReader
View via the ArticlePresentationModel
and NewsReaderPresenter
.
There is a discussion about the patterns used in Prism (and hence the sample application) in the guidance documentation, but the above helped to put things straight in my mind.
Getting Started
The first thing I did to get me started down the road to a Prism-based application was to implement the Bootstrapper, which I did as follows:
- Added references to the following Prism assemblies in my main (shell) project:
- Microsoft.Practices.Composite.dll
- Microsoft.Practices.Composite.Wpf.dll
- Microsoft.Practices.UnityExcetions.dll
- Microsoft.Practices.Unit.dll
- Microsoft.Practices.ObjectBuilder.dll
- Added a new class called
MyApplicationBootstrapper
2, which inherits from UnityBootstrapper
as shown in the following code example.
public class MyApplicationBootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
MainWindow window = new MainWindow();
window.Show();
return window;
}
protected override IModuleEnumerator GetModuleEnumerator()
{
return new StaticModuleEnumerator();
}
}
- Removed the
StartupUri
property from App.xaml.
- Created an instance 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();
}
2 I've substituted "MyApplication
" for the name of the actual application to protect the interests of my employer.
So far so good. The application runs as it did before but now it uses a Bootstrapper. Nothing dramatic and no big 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.
Note: I welcome (encourage even) any corrections/comments/etc. about the approach that I'm taking or on any of the details that I've included in this post (and future posts).