Introduction
This article is about a pair of Visual Studio project templates I have written, one for Silverlight and one for WPF. They provide similar output - a clean and minimal project that has a user interface inspired by Microsoft Zune. To see how it looks, you can look at the Silverlight version in your browser, download the demo applications or go ahead and install the Apex SDK and create a new project in Visual Studio 2010 from the templates!
[The WPF Template]
[The Silverlight Template - See it in action]
Using the Templates
Step 1: Install the Apex SDK
Installing the templates is very straightforward. First, download the Apex SDK (Apex is the MVVM Framework that these templates use) and run the installer.
Step 2: Create a New Project
Open Visual Studio 2010 and create a new project, you will see the following two new project templates in the C# section:
[The New Project Window]
Choose either the WPF and Silverlight project template. The project you have created can be run up immediately!
Step 3: Extend the Project
Now you've got a great starting point for a cool looking application have a look through the two articles below to find out more about how you can use Apex to build MVVM applications:
Apex Part 1: Create Your First MVVM Application
Apex Part 2: Adding Commands to an MVVM Application
Both of these articles also have YouTube videos if you don't feel like reading! You can also keep up with Apex releases, development and suggest features on the Apex CodePlex page.
How the Application Works
The application that is created is essentially the same in both the WPF and Silverlight flavors. There are only two key differences:
- The WPF Template styles the window chrome (the borders, minimize and maximize button etc)
- The Silverlight Template uses Visual States rather than triggers for animation
What is important is that the logical and key user interface elements of the application function exactly the same - this is one of the key points behind the Apex framework - code you write for WPF should be compatible with Silverlight and vice-versa.
In this section of the article, we'll go through everything that the template creates for you and how you can build upon it.
Part 1: The Main View and ViewModel
In the root of the solution there are two key files: MainViewModel.cs and MainView.cs.
The MainViewModel is just what is says - it's the main viewmodel for the application. It derives from PageViewModel, which is part of the template. PageViewModel has three properties - a title, a set of child pages and a selected page.
This is in fact all we need to get a working page system. The main viewmodel creates all of the child pages in its constructor, and the main view binds to it to show the application. Here's how it works:
[The Structure of the Main View]
The Shell
The first part of the main view is the Shell. This is a top level element defined in the Apex library that provides support for popups and drag and drop. In Silverlight you cannot show a separate popup window, but you can show user interface elements that look like popups. If you go to the Shell page in the sample and press the 'Show Popup' button you'll see a popup in action.
What's good about the shell is that it works consistently across WPF and Silverlight - so you don't have to deal with separate mechanisms for popups and drag and drop on different platforms.
If you ever need to get the shell, say to show a popup, you can do it via the ApexBroker - which handles access to all key elements:
IShell theShell = ApexBroker.GetShell();
theShell.ShowPopup(new ExamplePopup());
The Top Menu
The top menu is a SelectableItemsControl. This is derived from ItemsControl and allows you to have a set of items, but deal with selection, without having to re-template a ListBox or ListControl. It works by simply binding to the data (in this case the set of page viewmodels) and if they implement the 'ISelectableItem' interface then it will set their 'Selected' property and call 'OnSelected' and 'OnDeselected' for the items as appropriate as the user selects them.
The Bottom Menu
The top menu is a SelectableItemsControl and has a SelectedItem property. We bind to the Pages of the SelectedItem property of the top menu to show the child pages. This works in exactly the same way as the top menu.
The View Broker
The ViewBroker is a control that when given a ViewModel (such as our selected page) creates the appropriate view for it. This means as we switch between pages, the ViewBroker gets passed the selected viewmodel, and automatically creates a view for it. This a very useful feature, it is explained in detail in Part 3 below.
Part 2: The Model
In a folder named 'Models' two files will have been created - ApplicationModel.cs and IApplicationModel.cs, where Application is the name you chose for your project.
[The Solution Explorer, showing the models]
What we have is one model, and one model interface. The idea behind this, is that you define your model interface to describe all of the functions that the model should perform. It is only the interface of the model that other parts of the application will know about - never the implementation details. Here's the example:
public interface IExampleModel
{
IEnumerable<string> GetAlbums();
IEnumerable<string> GetArtists();
IEnumerable<string> GetTracks();
}
So in the model interface, we define only what the model can do. Then we have the model implementation:
[Model]
public class ExampleModel : IModel, IExampleModel
{
public void OnInitialised()
{
}
public IEnumerable<string> GetArtists()
{
yield return "John Coltrain";
In the model implementation you can do anything you want to fulfill the requirements defined in the interface - using a database connection, the file system, the web or whatever.
How Apex deals with Models
If you decorate your model implementation with the [Model] attribute, then Apex will automatically create one single instance of the model on application initialisation. If the implementation implements the IModel interface, then Apex will also call its OnInitialised function. What is key about this arrangement is the following - you can get a model from anywhere in code like this:
var exampleModel = ApexBroker.GetModel<IExampleModel>();
The ApexBroker is the object that you can use to get models, views, viewmodels and so on. The GetModel function allows you to request the model instance by asking for its interface. You can in fact remove the interface and just ask for the model class directly - but by just using the interface, we keep the code nicely separated - callers don't ever have any details of how the model is implemented - just access to its functionality.
This becomes particularly useful in more complex situations, where you may have a different model for testing, a different one for the design view and so on.
Part 3: The Page Views and ViewModels
Every page is made up of a view and a ViewModel. A page ViewModel looks like this:
[ViewModel]
public class MusicViewModel : PageViewModel
{
the [ViewModel] attribute tells Apex that it is a ViewModel and should be able to be used in the ApexBroker.
A View looks like this:
[View(typeof(MusicViewModel))]
public partial class MusicView : UserControl, IView
{
public MusicView()
{
Views have the [View] attribute, which they use to tell the ApexBroker they're views and also what their associated ViewModel type is. The IView interface has just two functions - OnActivated and OnDeactivated. Altogether what this means is that controls such as the ViewBroker can be given a ViewModel, create the correct View usercontrol, display it and call OnActivated so that the view knows its been shown. It is in the OnActivated that we fire off the animations that slide and fade in elements on the screen.
The Next Steps
It's up to you - hopefully you will find these templates useful. If you want to learn more about Apex in general, you can check the key articles below:
Apex Part 1: Create Your First MVVM Application
Apex Part 2: Adding Commands to an MVVM Application
Also, the CodePlex page should be the first page to visit for information on Apex:
Apex on CodePlex
I am more than happy to answer any questions and any feedback, comments, or ideas are always welcome! Also, if you create anything funky looking with this template then feel free to send over some screenshots, I'd like to create a gallery of images of applications that have used the template.