After my initial successes in moving to a Prism-style bootstrapper in Part 1, it was time to move onto the next step. But in the case of a legacy application, what's the next step?
Application Structure Overview
Our 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 those 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.
There are two main entities, one that relates to a Project that is handled by the application and one that relates to Pages, which make up the contents of a Project. So these seemed to me to be good choices for modules. But, the existing infrastructure merges the roles of Service and ViewModel into a single class, which I'd like to separate.
So, my plan (so far at least) is to create Prism Modules for the Project and Page and 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, I'm planning on writing a Prism-facade 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 rip out the heart of the application and re-write it completely, which would be a costly and time consuming task.
For my next step, I'm focusing on the Project aspects of the application, so (as you can see in the screen shot above) I've created a Project module containing the
ProjectTreeViewModel and a
ProjectController, which will handle the interactions between the different views of a project (when I get that far).
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, my implementations are very simple in that they just initialise the relevant Views, ViewModels, etc. The View itself is simply a UserControl that contains a root Grid element with a pink background. The important thing is to get it loaded and displayed first.
In the application's shell, the existing user control was removed and replaced with the following region definition.
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.
ProjectController 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 in the following code example:
public void Run()
IRegion region = this._regionManager.Regions[RegionNames.Navigation];
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.
Run method of the
ProjectController is called in the
Initialize method of the
ProjectModule after registering the required views and services, as shown in the following code example:
#region Private Methods private void RegisterViewsAndServices()
#endregion Private Methods #region IModule Members
public void Initialize()
IProjectController controller = this._container.Resolve<IProjectController>();
As you can see in the screen shot above, apart from writing all the tests, putting some simple content in the ViewModel, a bit of work on the infrastructure and doing a lot of head scratching, that's it! Granted it's just a pink rectangle at the moment, but I now have a View that is loaded into the right place.
My next step is to put some useful UI code into the View and try to gradually incorporate some of the visual functionality of its predecessor.