Silverlight class library not included in .XAP

This is something I’m sure I ran into before, but it still bit me the other day. Hopefully by writing this down here it won’t get me again.

The problem is this: A Silverlight class library whose name ends with “.Resources” is not included in the Silverlight .XAP file.

“.Resources” is a reserved naming convention (I guess) that shouldn’t be used. The solution to including such DLL’s in the .XAP file is to rename it so it ends with something like “.SharedResources.dll”.

Short post. Odd problem. Easy solution

I’ve been immersing myself in the Model-View-ViewModel (MVVM) design pattern of late. The pattern derives from Model-View-Presenter (MVP), which in turn has its roots in the Model-View-Controller (MVC) pattern. MVVM takes MVP one step further by gearing itself specifically towards WPF/Silverlight style development. While both WPF and Silverlight have built-in support for implementing MVVM (commanding, bindings, behaviors via the Expression Blend SDK), they do so with varying depth, and, even still, both fall short in terms of providing comprehensive support. Fortunately, a wide array of MVVM frameworks have cropped up to fill in these holes.

In this post I wanted to go through the motions of setting up a skeleton Silverlight project that utilizes MVVM. The application doesn’t do much (it displays a random number in response to user input), but it does demonstrate some of the basic facilities we can use to implement the MVVM pattern, namely commanding and binding. One of the primary goals of MVVM is to remove the (often tight) coupling between the presentation layer (XAML) and the business logic (code-behind). Some argue that the pattern is overrated; we’re simply removing logic from the code-behind and putting it into the ViewModel. This is true to some extent. But if you create a true separation between your UI and logic, and you take full advantage of the platform’s support for MVVM, ultimately you’ll find yourself writing less code. That’s a good thing.

Much of what I show below is encapsulated in the various MVVM frameworks. I’m ignoring those for now because I want to establish a deeper understanding of the implementation mechanics. Moving forward, I will most certainly be adopting one of the frameworks.

Now, on to the code…

The Silverlight MVVM Project

1. Create a new Silverlight project

Standard stuff. Create a new Silverlight project, giving it a host web site. I called mine “MVVMBase”.

2. Add three new folders to the Silverlight project

imageThe three folders are:

  1. MVVMFramework
  2. ViewModels
  3. Views

3. In the MVVMFramework folder, add support classes

These are the classes that any of the MVVM frameworks will supply for you. Even if you choose to not use one of the frameworks and roll your own, you’ll likely want to place these objects in their own reusable class library since any MVVM project will make use of them. As noted above, I’m rolling my own here simply as a learning exercise.

Here are the classes. There are three of them.

a. Observable

When we define our own ViewModel classes, it is necessary that those objects derive from INotifyPropertyChanged because we’ll be using the class in binding operations. Normally, you might create a ViewModelBase class, derive it from INotifyPropertyChanged, and you’re done.  It’s been suggested by some, however, to separate out INotifyPropertyChanged functionality from the base ViewModel class since there are instances other than when defining a ViewModel where you might want to derive from INotifyPropertyChanged. That’s what I’ve done here. Observable is defined as:

   1: namespace MVVMBase.MVVMFramework
   2: {
   3:     using System.ComponentModel;
   4:     using System.Windows;
   5:
   6:     public class Observable : INotifyPropertyChanged
   7:     {
   8:         public event PropertyChangedEventHandler PropertyChanged;
   9:
  10:         protected void NotifyPropertyChanged (string propertyName)
  11:         {
  12:             if (PropertyChanged != null)
  13:             {
  14:                 PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
  15:             }
  16:         }
  17:     }
  18: }
View Plain

b. ViewModelBase

It’s convenient to have a ViewModel base class from which your own ViewModel classes can derive. For purposes of this post, mine doesn’t do much except derive from Observable:

   1: namespace MVVMBase.MVVMFramework
   2: {
   3:     public class ViewModelBase : Observable
   4:     {
   5:     }
   6: }
View Plain

c. RelayCommand

WPF introduced something called Commanding, which allows you to bind a user event (like a button click) to execution logic where the binding is done in XAML. User-defined commands are derived from ICommand; you need to have one defined per command event. Of course, if you define a new ICommand for each and every command, you’ll quickly have a lot of repetitive code. Fortunately, there’s a better way.

RelayCommand (alternatively named DelegateCommand or ViewModelCommand by others) is a generic class that derives from ICommand. It takes as parameters an Action and a Predicate, which define ICommand’s Execute and CanExecute methods which RelayCommand must implement.

Here’s the code:

   1: namespace MVVMBase.MVVMFramework
   2: {
   3:     using System;
   4:     using System.Windows.Input;
   5:
   6:     public class RelayCommand : ICommand
   7:     {
   8:         private readonly Action<object> _executeAction;
   9:
  10:         private readonly Predicate<object> _canExecute;
  11:
  12:         public RelayCommand (Action<object> executeAction, Predicate<object> canExecute)
  13:         {
  14:             if (executeAction == null)
  15:             {
  16:                 throw new ArgumentNullException ("executeAction");
  17:             }
  18:
  19:             _executeAction = executeAction;
  20:             _canExecute = canExecute;
  21:         }
  22:
  23:         public event EventHandler CanExecuteChanged;
  24:
  25:         public void OnCanExecuteChanged ()
  26:         {
  27:             if (CanExecuteChanged != null)
  28:             {
  29:                 CanExecuteChanged (this, EventArgs.Empty);
  30:             }
  31:         }
  32:
  33:         /// <summary>
  34:         /// Defines the method that determines whether the command can execute in its current state.
  35:         /// </summary>
  36:         /// <returns>True if this command can be executed; otherwise, false.</returns>
  37:         /// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
  38:         public bool CanExecute (object parameter)
  39:         {
  40:             return _canExecute == null || _canExecute (parameter);
  41:         }
  42:
  43:         /// <summary>
  44:         /// Defines the method to be called when the command is invoked.
  45:         /// </summary>
  46:         /// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
  47:         public void Execute (object parameter)
  48:         {
  49:             _executeAction (parameter);
  50:         }
  51:     }
  52: }
View Plain

4. In the ViewModels folder, add a new class called “MainPageViewModel”

This is our ViewModel, derived from ViewModelBase, which contains the business logic for updating our View. Note that the ViewModel doesn’t update the View directly. Instead, it updates properties that have been bound to the View in the View’s XAML.

   1: namespace MVVMBase.ViewModels
   2: {
   3:     using MVVMBase.MVVMFramework;
   4:
   5:     using RandomNumber;
   6:
   7:     public class MainPageViewModel : ViewModelBase
   8:     {
   9:         private IGenerateNumber _generateNumber;
  10:
  11:         private string _number;
  12:
  13:         public MainPageViewModel (IGenerateNumber generateNumber)
  14:         {
  15:             _generateNumber = generateNumber;
  16:
  17:             GetNumberCommand = new RelayCommand (GetNumber, CanGetNumber);
  18:         }
  19:
  20:         public RelayCommand GetNumberCommand { get; private set; }
  21:
  22:         public string Number
  23:         {
  24:             get
  25:             {
  26:                 return _number;
  27:             }
  28:
  29:             private set
  30:             {
  31:                 if (value == _number)
  32:                     return;
  33:
  34:                 _number = value;
  35:
  36:                 NotifyPropertyChanged ("Number");
  37:             }
  38:         }
  39:
  40:         private void GetNumber (object parameter)
  41:         {
  42:             Number = _generateNumber.GetRandomNumber ().ToString ();
  43:         }
  44:
  45:         private bool CanGetNumber (object parameter)
  46:         {
  47:             return true;
  48:         }
  49:     }
  50: }
View Plain

The constructor takes an interface to GenerateNumber, which is just a class library whose code is included in the download (see below). This service class generates a random number and returns it to the caller via the GetRandomNumber method.

GetNumber and CanGetNumber correspond to the RelayCommand’s Action and Predicate delegates. ICommand gives us the ability to turn off a feature via a CanExecute method and to execute some logic in response to a command via a Execute method. That’s the role these two delegates play. In CanGetNumber I simply return ‘true’; in a real application you might have logic here that actually checks conditions and then possibly returns false if you do not want the command to execute. GetNumber runs if and when CanExecute evaluates to ‘true’. Here it initializes the POCO property Number with a new random number. See the discussion beneath the View code for what’s going on behind the scenes.

5. In the Views folder, copy over and rename MainPage.xaml/.cs

MainPage.xaml/.cs was created when you created the Silverlight project. Rename it to MainPageView.xaml/.cs and copy it into the Views folder (you don’t have to rename it, but I do just for naming consistency; remember to rename the class, too).

First, let’s look at the codebehind:

   1: namespace MVVMBase.Views
   2: {
   3:     using System.Windows.Controls;
   4:
   5:     public partial class MainPageView : UserControl
   6:     {
   7:         public MainPageView ()
   8:         {
   9:             InitializeComponent ();
  10:         }
  11:     }
  12: }
View Plain

As we intended, it pretty much contains nothing. This is as it should be when implementing the MVVM pattern, though note that achieving this ideal while easy in a small project like this one, can be very difficult and almost counter-productive in a real-world, complex application.

Next, take a look at the MainPageView.xaml file:

   1: <UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="MVVMBase.Views.MainPageView"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   5:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   6:     mc:Ignorable="d"
   7:     d:DesignHeight="200" d:DesignWidth="150">
   8:
   9:     <StackPanel x:Name="LayoutRoot" Orientation="Vertical" Background="White" VerticalAlignment="Center">
  10:         <sdk:Label Content="{Binding Number}" Height="30" Width="100" Background="AliceBlue" Margin="10" />
  11:         <Button Content="Get Number" Height="30" Width="100" Margin="10" Command="{Binding GetNumberCommand}" />
  12:     </StackPanel>
  13: </UserControl>
View Plain

The important stuff is on lines 10-11.

On Line 10, we define a Label whose Content is bound to a property called “Number”. If you go back and look at the ViewModel, you’ll see I defined a POCO property there that corresponds to this binding. The magic is the call to NotifyPropertyChanged, which notifies the binding framework that this property’s value has changed. This in turn triggers an update to our UI because of the Binding we set up.

On Line 11, we declare a Button whose Command property is bound to something called “GetNumberCommand”. Again, looking back at MainPageViewModel, you’ll see a RelayCommand that corresponds to this binding.

6. Connect the View to the ViewModel

At this point we have all the infrastructure in place for a basic Silverlight MVVM application. But we still need to connect the View to the ViewModel. There are several philosophies out there on how best to do this. The basic options are these (Pete Brown touches on these approaches in his book, Silverlight 4 in Action):

1.) The code owns the ViewModel

In this approach you instantiate the ViewModel in the View’s code-behind and assign it to the View’s DataContext. While straightforward, this is not a recommended approach mostly because you’ve created a situation where the View cannot be used without also pulling the ViewModel along with it.

2.) The markup owns the ViewModel

This is essentially the same thing as the previous approach except in this case you declare the ViewModel in the View’s XAML. Again, while relatively straightforward, you’re creating a tightly bound relationship between the View and the ViewModel. This isn’t necessarily a bad thing; in MVVM, a View is going to have a ViewModel, right? The truth of the matter is that either this approach or the previous one works perfectly fine. But option #3 has the added benefit of additional flexibility.

3.) The ViewModel is provided externally

In this approach the ViewModel is instantiated externally from the View and the two are bound together outside of either the View or the ViewModel. The benefit of this is a more loosely coupled arrangement, enhanced testability, and the ability to inject a different ViewModel for a given View rather than just the default. This is the approach I took.

In App.xaml.cs, I added the following code to the Application_Startup event:

   1: var mainPageViewModel = new MainPageViewModel (new GenerateNumber ());
   2: RootVisual = new MainPageView { DataContext = mainPageViewModel };
View Plain

First, instantiate the ViewModel, passing in a GenerateNumber object via constructor injection (GenerateNumber is a service class that generates a random number; download the sample code to see it in all it’s glory). Then, new up the View, setting it’s DataContext to the ViewModel while also assigning the View itself to the application’s RootVisual property.

It’s setting the View’s DataContext to the ViewModel class which essentially “glues” the ViewModel to the View. Also, if we wanted to use a different ViewModel with this View (or have several Views of this type each with a different ViewModel type), it’s as simple as assigning each ViewModel type to the View’s DataContext. You’d have some difficulty doing that with either of the other ownership approaches above.

Leave a Reply

Your email address will not be published. Required fields are marked *