Click here to Skip to main content
Click here to Skip to main content

A Zune Style Application Template for WPF and Silverlight

, 25 Jun 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
A Zune Style Application Template that makes a great starting point for WPF or Silverlight Projects

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: 

  1. The WPF Template styles the window chrome (the borders, minimize and maximize button etc)
  2. 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:

//  Get the shell and show the example popup.
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: 

    /// <summary>
    /// The Example Model interface.
    /// </summary>
    public interface IExampleModel
    {
        /// <summary>
        /// Gets the ablums.
        /// </summary>
        IEnumerable<string> GetAlbums();
 
        /// <summary>
        /// Gets the artists.
        /// </summary>
        IEnumerable<string> GetArtists();
 
        /// <summary>
        /// Gets the tracks.
        /// </summary>
        IEnumerable<string> GetTracks();
    } 

So in the model interface, we define only what the model can do. Then we have the model implementation:

    /// <summary>
    /// The Example Model. Can be accessed via ApexBroker.GetModel
    /// via the interface IExampleModel.
    /// </summary>
    [Model]
    public class ExampleModel : IModel, IExampleModel
    {
        /// <summary>
        /// Called to initialise a model.
        /// </summary>
        public void OnInitialised()
        {
            //  TODO: Initialise your model here.
        }
 
        /// <summary>
        /// Gets the artists.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<string> GetArtists()
        {
            yield return "John Coltrain";
            
            //  etc etc etc

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:

//  Get the example model.
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:

/// <summary>
/// The MusicViewModel ViewModel class.
/// </summary>
[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:

/// <summary>
/// Interaction logic for MusicView.xaml
/// </summary>
[View(typeof(MusicViewModel))]
public partial class MusicView : UserControl, IView
{
    public MusicView()
    {
        // ...etc... 

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. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Dave Kerr
Software Developer
United Kingdom United Kingdom
Follow my blog at www.dwmkerr.com and find out about my charity at www.childrenshomesnepal.org.
Follow on   Twitter

Comments and Discussions

 
QuestionFramework ? Pinmembercassini0116-Apr-14 5:20 
AnswerRe: Framework ? PinmvpDave Kerr16-Apr-14 6:13 
GeneralMy vote of 5 PinmemberDotNetMastermind29-Jan-13 22:57 
GeneralRe: My vote of 5 PinmvpDave Kerr6-Mar-13 5:48 
QuestionFinally something easy to implement (my 5) Pinmembermeraydin11-Nov-12 20:58 
AnswerRe: Finally something easy to implement (my 5) PinmvpDave Kerr14-Dec-12 5:26 
QuestionNo refresh of controls with AsyncCommand [modified] PinmemberFrank23117-Sep-12 0:23 
AnswerRe: No refresh of controls with AsyncCommand PinmvpDave Kerr14-Dec-12 5:24 
QuestionProblem in running example and installing Apex SDK Pinmemberyccheok5-Sep-12 23:53 
AnswerRe: Problem in running example and installing Apex SDK Pinmemberjlopez78814-Dec-12 4:56 
GeneralRe: Problem in running example and installing Apex SDK PinmvpDave Kerr14-Dec-12 5:24 
QuestionNot Working =( PinmemberDelrone20002-Sep-12 13:41 
AnswerRe: Not Working =( PinmvpDave Kerr14-Dec-12 5:23 
GeneralRe: Not Working =( PinmemberZeljko Petrusic6-Mar-13 2:23 
AnswerRe: Not Working =( PinmemberTDaddy Hobz7-May-13 23:49 
GeneralRe: Not Working =( PinmvpDave Kerr10-May-13 1:18 
Questiongreat job Pinmemberzlh_1001-Aug-12 1:53 
AnswerRe: great job PinmvpDave Kerr1-Aug-12 2:00 
Questionwork is really done good. Pinmemberiestar3-Jul-12 22:33 
AnswerRe: work is really done good. PinmvpDave Kerr4-Jul-12 1:33 
GeneralMy vote of 5 PinmentorMd. Marufuzzaman3-Jul-12 11:24 
GeneralRe: My vote of 5 PinmvpDave Kerr4-Jul-12 1:34 
GeneralRe: My vote of 5 PinmentorMd. Marufuzzaman4-Jul-12 19:56 
GeneralVery good Project PinmemberMember 86915452-Jul-12 21:14 
GeneralRe: Very good Project PinmvpDave Kerr2-Jul-12 21:16 
GeneralNice job, my vote is 5. PinmemberTracert26-Jun-12 13:28 
GeneralRe: Nice job, my vote is 5. PinmvpDave Kerr26-Jun-12 22:22 
GeneralMy vote of 5 PinmvpSacha Barber21-Jun-12 22:02 
QuestionVery nice PinmvpSacha Barber21-Jun-12 22:02 
AnswerRe: Very nice PinmvpDave Kerr21-Jun-12 22:21 
GeneralRe: Very nice PinmvpSacha Barber22-Jun-12 4:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411023.1 | Last Updated 26 Jun 2012
Article Copyright 2012 by Dave Kerr
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid