This is the first post of a series in three parts where I will discuss what are the “must have” of any of my WPF/MVVM projects. This one is about dealing with design time data with the framework MVVM light. The sample project of this post can be found here on my github.
When we speak of design time data in a WPF project, we refer to the data that will be visible in the Visual Studio designer. In the picture below the data displayed have no reason to be related to production or any testing dataset. They serve the only purpose of designing your app. It is important to be aware that the Visual Studio designer is extremely powerful and is able to execute some of the .NET code of your app. I have noticed also that the VS WPF designer have improved a lot with VS 2012.
Why having design time data is ABSOLUTELY mandatory? First, some controls do not need data to be designed. Take a Button for example, its Content (the label) is probably static then you will not have any troubles designing it. On the contrary, if you take the DataGrid in the screenshot above, the rows are dynamic data so you won’t be able to see some lines in your VS designer unless you specify some design time data.
Now let me tell you a story. I learnt WPF because I was affected to an Excel addin project that had been started two years before. The screens had been developed using WPF but without any pattern, only (spaghetti) code behind. In addition to the fact that nothing was testable and the business logic was tightly coupled to the presentation, there was no design time data for the WPF screens. Sometimes, in order to view the effect of a single border color modification, the developer had to start the addin, connect some web services, fetch (potentially large) data etc… All of this was dramatic in terms of efficiency. A complete reskin of the application was not even thinkable. Let me conclude this argumentation by saying that some data are not easily produced with a test dataset. For example, if you have a Textblock displaying a path on your hardrive. You would like to see if it is still ok if this path becomes very long. If you do not have design time data, you will have to create such a deep folder hierarchy in your drive, only to see the behavior of your TextBlock control style. This is a pity, using design time data, you may insert any string in the control in less than a second.
How do you do that in practice with an MVVM project? We are going to take a very simple sample project (that can be found here). This application is a window with two tabs to display some information about book authors. You can select the author with a Combobox. On the first tab, there is basic information about the author while on the second tab there is the list of the books written by this author. Implementing this with MVVM: you will have three views (.xaml files): one the main window, two for the tabs.
In my WPF apps, all view models are specified through interfaces. Then, for the sample project, we have the three following interfaces: IMainViewModel, ISummaryTabViewModel and IBooksWrittenTabViewModel. ISummaryTabViewModel and IBooksWrittenTabViewModel are “sub view models”. Naturally, they are exposed as member of the IMainViewModel.
For each view model there are two implementations: the production implementation and the design implementation. I like to separate in another namespace the design time implementations to avoid “solution explorer visual pollution”.
We use a ViewModelLocator so that the views can find the appropriate implementation of the view model interface. Typically, the ViewModelLocator exposes a static property for the “top” rooted view model.
In the sample above, I kept the IoC Ninject container (the _kernel field). You may ignore this but the ViewModelLocator is the composition root of the application, this is where an IoC Container should be used, see this post for more information.
All the magic lies in the if statement ViewModelBase.IsInDesignModeStatic which is provided by the amazing MVVM Light Framework developed by Laurent Bugnion. It will detect if the call to the ViewModelLocator comes from the Visual Studio Designer or if the application is truly running.
If you create a multi lang app with the approach detailed in one of my previous posts you can change within the if(ViewModelBase.IsInDesignModeStatic) scope the CurrentUICulture to design and see your app with any supported languages.
Now the ViewModelLocator is manipulated in the views as follows In MainWindow.xaml
In SummaryTabControl.xaml the control DataContext is bound to the SummaryTabViewModel property of the IMainViewModel.
The Locator resource has been declared in the App.xaml
Let us have a look at the DesignMainViewModel class
and the SummaryTabViewModel class
When implementing the “Design” view models it is important to avoid implementing any business logic. If the fake data are incoherent between the several view models design implementations that should not trouble you either. To conclude, in a real app, you will probably have to create design implementation not only for the view models but also for the objects used in data bindings (e.g. the interface IBook).
This is the end of the first part of the WPF/MVVM “must have” series. The second article will deal with the organization of the unit tests of an MVVM application.