Click here to Skip to main content
11,490,282 members (34,319 online)
Click here to Skip to main content

A Zune Style Application Template for WPF and Silverlight

, 25 Jun 2012 CPOL 39.7K 7.7K 83
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

 
Questionapex Pin
yiyu112122-Apr-15 0:21
memberyiyu112122-Apr-15 0:21 
QuestionFramework ? Pin
cassini0116-Apr-14 5:20
membercassini0116-Apr-14 5:20 
AnswerRe: Framework ? Pin
Dave Kerr16-Apr-14 6:13
mvpDave Kerr16-Apr-14 6:13 
GeneralMy vote of 5 Pin
DotNetMastermind29-Jan-13 22:57
memberDotNetMastermind29-Jan-13 22:57 
GeneralRe: My vote of 5 Pin
Dave Kerr6-Mar-13 5:48
mvpDave Kerr6-Mar-13 5:48 
QuestionFinally something easy to implement (my 5) Pin
meraydin11-Nov-12 20:58
membermeraydin11-Nov-12 20:58 
AnswerRe: Finally something easy to implement (my 5) Pin
Dave Kerr14-Dec-12 5:26
mvpDave Kerr14-Dec-12 5:26 
QuestionNo refresh of controls with AsyncCommand [modified] Pin
Frank23117-Sep-12 0:23
memberFrank23117-Sep-12 0:23 
AnswerRe: No refresh of controls with AsyncCommand Pin
Dave Kerr14-Dec-12 5:24
mvpDave Kerr14-Dec-12 5:24 
QuestionProblem in running example and installing Apex SDK Pin
yccheok5-Sep-12 23:53
memberyccheok5-Sep-12 23:53 
AnswerRe: Problem in running example and installing Apex SDK Pin
jlopez78814-Dec-12 4:56
memberjlopez78814-Dec-12 4:56 
GeneralRe: Problem in running example and installing Apex SDK Pin
Dave Kerr14-Dec-12 5:24
mvpDave Kerr14-Dec-12 5:24 
QuestionNot Working =( Pin
Delrone20002-Sep-12 13:41
memberDelrone20002-Sep-12 13:41 
AnswerRe: Not Working =( Pin
Dave Kerr14-Dec-12 5:23
mvpDave Kerr14-Dec-12 5:23 
GeneralRe: Not Working =( Pin
Zeljko Petrusic6-Mar-13 2:23
memberZeljko Petrusic6-Mar-13 2:23 
AnswerRe: Not Working =( Pin
TDaddy Hobz7-May-13 23:49
memberTDaddy Hobz7-May-13 23:49 
GeneralRe: Not Working =( Pin
Dave Kerr10-May-13 1:18
mvpDave Kerr10-May-13 1:18 
Questiongreat job Pin
zlh_1001-Aug-12 1:53
memberzlh_1001-Aug-12 1:53 
AnswerRe: great job Pin
Dave Kerr1-Aug-12 2:00
mvpDave Kerr1-Aug-12 2:00 
Questionwork is really done good. Pin
iestar3-Jul-12 22:33
memberiestar3-Jul-12 22:33 
AnswerRe: work is really done good. Pin
Dave Kerr4-Jul-12 1:33
mvpDave Kerr4-Jul-12 1:33 
GeneralMy vote of 5 Pin
Md. Marufuzzaman3-Jul-12 11:24
mentorMd. Marufuzzaman3-Jul-12 11:24 
GeneralRe: My vote of 5 Pin
Dave Kerr4-Jul-12 1:34
mvpDave Kerr4-Jul-12 1:34 
GeneralRe: My vote of 5 Pin
Md. Marufuzzaman4-Jul-12 19:56
mentorMd. Marufuzzaman4-Jul-12 19:56 
GeneralVery good Project Pin
Member 86915452-Jul-12 21:14
memberMember 86915452-Jul-12 21:14 
GeneralRe: Very good Project Pin
Dave Kerr2-Jul-12 21:16
mvpDave Kerr2-Jul-12 21:16 
GeneralNice job, my vote is 5. Pin
Tracert26-Jun-12 13:28
memberTracert26-Jun-12 13:28 
GeneralRe: Nice job, my vote is 5. Pin
Dave Kerr26-Jun-12 22:22
mvpDave Kerr26-Jun-12 22:22 
GeneralMy vote of 5 Pin
Sacha Barber21-Jun-12 22:02
mvpSacha Barber21-Jun-12 22:02 
QuestionVery nice Pin
Sacha Barber21-Jun-12 22:02
mvpSacha Barber21-Jun-12 22:02 
AnswerRe: Very nice Pin
Dave Kerr21-Jun-12 22:21
mvpDave Kerr21-Jun-12 22:21 
GeneralRe: Very nice Pin
Sacha Barber22-Jun-12 4:41
mvpSacha 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.150520.1 | Last Updated 26 Jun 2012
Article Copyright 2012 by Dave Kerr
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid