I was pleasantly surprised to see in the Silverlight 4 feature list that it will be possibly to setup Bindings on DependencyObjects (as opposed to FrameworkElements) in the same way you can with WPF. This greatly affects in my opinion the benefits of Blend Triggers, Actions and Behaviors, being able to bind them to other elements or a ViewModel (if using the MVVM pattern) lets you set up some really cool stuff.
A while ago I talked about using Blend Behaviors to wire together triggers to commands. It was possible, but required a lot of wiring code in order to expose Binding objects and listen for changes. With Silverlight 4 it becomes a lot simpler and lot more readable. The full code is for ExecuteTriggerAction is:
public class ExecuteCommandAction : TriggerAction<DependencyObject>
{
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(ExecuteCommandAction), null);
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter", typeof(object), typeof(ExecuteCommandAction), null);
public ICommand Command
{
get
{
return (ICommand)GetValue(CommandProperty);
}
set
{
SetValue(CommandProperty, value);
}
}
public object CommandParameter
{
get
{
return GetValue(CommandParameterProperty);
}
set
{
SetValue(CommandParameterProperty, value);
}
}
protected override void Invoke(object parameter)
{
if(Command != null && Command.CanExecute(CommandParameter))
Command.CanExecute(CommandParameter);
}
}

So I've been going over this with a few others lately, is ensuring your project is "Blendable" worth it?
The Model, View, ViewModel pattern does a great job in separating the UI from the logic for each screen, at some point however they have to be integrated. This has been the part I've been showing in the screencasts of this series. Going over this I feel there are a few areas that ensure good usage of Expression Blend.
-
Being able to create and edit a View using Blend, ultimately this means a parameter-less constructor no business logic in the constructor (shouldn't be doing this with MVVM anyway).
-
Being able to integrate the View and ViewModel, originally I tried to use the Blend UI as much as possible for this, but ultimately I don't think it's feasible, a lot of the integration will be done in xaml. The Blend UI doesn't have enough features to be able to do all the integration, it could be possible with a plethora of Behaviors for each custom task but it could get complicated.
Overall while Blend is a great tool for putting together your view it doesn't do well for integrating the view and view model. I think it's still useful to ensure Blend is usable, but limiting yourself to only what you can do in the Blend UI is counter productive.
In the previous posts we've been retrieving our data from a synchronous data source, for the most part in Silverlight we'll be retrieving data sources from aseparate server, in this case through a WCF Service. Silverlight has a restriction that all network calls must be asynchronous in order to avoid locking up the browser UI (a good thing). It does however make the code a little more complicated.
The functionality of the CocktailsService will stay the same, we're just going to migrate it over to the server and host it as a WCF service. The code for the service is remains exactly the same, just shifted now to the server and hosted as a WCF service. If you'd like to learn more about setting up a WCF service you can read more on MSDN.
[ServiceContract]
public interface ICocktailService
{
[OperationContract]
IEnumerable<Cocktail> GetCocktails();
[OperationContract]
IEnumerable<Cocktail> GetCocktailsSimilarTo(Cocktail cocktail);
}
Then we generate a client proxy using Visual Studios "Add Service Reference". The proxy generated includes any types from the data contracts (the Cocktail class), the proxy client (CocktailsServiceClient) and a service interface (ICocktailsService). One thing to notice if you've done any WCF work before is that the interface doesn't contain the events exposed by the actual client class.
We'll now need to alter our Cocktails view model to deal with the new interface. Basically it's a relatively simple change from synchronous methods to using async ones. It should look like this...
public class CocktailsViewModel : ViewModelBase<CocktailsViewModel>
{
private readonly ICocktailService cocktailService;
public CocktailsViewModel(ICocktailService cocktailService)
{
this.cocktailService = cocktailService;
AvailableCocktails = new ObservableCollection<Cocktail>();
SimilarCocktails = new ObservableCollection<Cocktail>();
GetSimilarCocktailsCommand = new DelegateCommand<Cocktail>(GetSimilarCocktails);
cocktailService.BeginGetCocktails(OnGetCocktails, null);
}
private void OnGetCocktails(IAsyncResult ar)
{
var cocktails = cocktailService.EndGetCocktails(ar);
AvailableCocktails.AddRange(cocktails);
}
public ObservableCollection<Cocktail> AvailableCocktails
{
get;
set;
}
public ObservableCollection<Cocktail> SimilarCocktails
{
get;
set;
}
public ICommand GetSimilarCocktailsCommand
{
get;
private set;
}
protected void GetSimilarCocktails(Cocktail cocktail)
{
cocktailService.BeginGetCocktailsSimilarTo(cocktail, OnGetCocktailsSimilarTo, null);
}
private void OnGetCocktailsSimilarTo(IAsyncResult ar)
{
var cocktails = cocktailService.EndGetCocktailsSimilarTo(ar);
SimilarCocktails.Replace(cocktails);
}
}
There is a slight problem with the code above. Silverlight expects property changed notifications (including collection changed from ObservableCollection) to be on the UI thread. The async result methods will be on a separate thread (The generated service client will dispatch the OnXCompleted events back to the UI thread but not the asynch methods). There a couple of ways we can solve this.
- Manually dispatch any updates to properties back to the UI thread.
- Create our own ObservableCollection that ensures all notifications are on the correct thread. An example of this can be found at "Adding to an ObservableCollection from a background thread"
For this example we'll just be going with the first. We'll update our ViewModelBase to take a reference to the Application dispatcher and have a simple helper method.
protected ViewModelBase()
{
Dispatcher = Deployment.Current.Dispatcher;
}
protected Dispatcher Dispatcher
{
get; private set;
}
protected void InvokeOnUIThread(Action action)
{
Dispatcher.BeginInvoke(action);
}
We then alter the offending methods to use the helper.
private void OnGetCocktails(IAsyncResult ar)
{
var cocktails = cocktailService.EndGetCocktails(ar);
InvokeOnUIThread(() => AvailableCocktails.AddRange(cocktails));
}
private void OnGetCocktailsSimilarTo(IAsyncResult ar)
{
var cocktails = cocktailService.EndGetCocktailsSimilarTo(ar);
InvokeOnUIThread(() => SimilarCocktails.Replace(cocktails));
}
Our updates to the collections will be dispatched off to the UI thread and the exception will be avoided.

There are a couple of great reasons for using a UI separation pattern such as Model, View, ViewModel (or the more common MVP and MVC), the first being that with the application logic separated from the view logic the application becomes easier to maintain. Secondly it's usually easier for a designer and developer to work on the separate areas and integrate them at a later date (this actually helps enforce the separation). And thirdly by having the application logic away from the UI it becomes much easier to test.
While you can do UI testing with the Silverlight testing framework it becomes a hell of a lot easier when you have a nice separation. We're doing to be using a dependency injection framework (in this caseNinject) to build the view models and inject the services. This'll allow us to do interaction based unit testing on the view model using Rhino Mocks.
Overall our goal will be to refactor the existing ViewModel to break it's dependency on CocktailsService and increase it's testability. We'll create a Service Locator that will be an Application resource and serve as almost a "ViewModel factory" and then instead of directly creating our ViewModel in xaml we'll bind our Data Context to the Service Locator.
Our first step will be inverting the dependency the ViewModel has on the Cocktails Service, we'll extract an interface for the service and use constructor injection to pass the service to the ViewModel where it'll be stored, otherwise the view model remains the same.
public interface ICocktailService
{
IEnumerable<Cocktail> GetCocktails();
IEnumerable<Cocktail> GetCocktailsSimilarTo(Cocktail cocktail);
}
public CocktailsViewModel(ICocktailService cocktailService)
{
this.cocktailService = cocktailService;
AvailableCocktails = new ObservableCollection<Cocktail>();
SimilarCocktails = new ObservableCollection<Cocktail>();
GetSimilarCocktailsCommand = new DelegateCommand<Cocktail>(GetSimilarCocktails);
AvailableCocktails.AddRange(cocktailService.GetCocktails());
}
We can now test that the ViewModel exposes the available Cocktails, passes the command parameter to the service and exposes the similar cocktails.
[TestClass]
public class CocktailsViewModelFixture
{
private readonly List<Cocktail> sampleCocktails = new List<Cocktail>
{
new Cocktail
{
Id = 1,
Ingredients = new string[] {},
Name = "Test"
}
};
[TestMethod]
public void ConstuctionRetrievesAvailableCockstails()
{
var cocktailService = MockRepository.GenerateMock<ICocktailService>();
cocktailService.Expect(c => c.GetCocktails()).Return(Enumerable.Empty<Cocktail>());
new CocktailsViewModel(cocktailService);
cocktailService.VerifyAllExpectations();
}
[TestMethod]
public void ConstuctionExposesAvailableCockstails()
{
var cocktailService = MockRepository.GenerateStub<ICocktailService>();
cocktailService.Stub(c => c.GetCocktails()).Return(sampleCocktails);
var viewModel = new CocktailsViewModel(cocktailService);
Assert.AreEqual(sampleCocktails.Count, viewModel.AvailableCocktails.Count);
}
[TestMethod]
public void GetSimilarCocktailsForwardsCommandParameter()
{
var selectedCocktail = new Cocktail();
var cocktailService = MockRepository.GenerateMock<ICocktailService>();
cocktailService.Stub(c => c.GetCocktails()).Return(Enumerable.Empty<Cocktail>());
cocktailService.Expect(c => c.GetCocktailsSimilarTo(selectedCocktail)).Return(Enumerable.Empty<Cocktail>());
var viewModel = new CocktailsViewModel(cocktailService);
viewModel.GetSimilarCocktailsCommand.Execute(selectedCocktail);
cocktailService.VerifyAllExpectations();
}
[TestMethod]
public void GetSimilarCocktailsExposesSimilarCocktails()
{
var selectedCocktail = new Cocktail();
var cocktailService = MockRepository.GenerateMock<ICocktailService>();
cocktailService.Stub(c => c.GetCocktails()).Return(Enumerable.Empty<Cocktail>());
cocktailService.Stub(c => c.GetCocktailsSimilarTo(selectedCocktail)).Return(sampleCocktails);
var viewModel = new CocktailsViewModel(cocktailService);
viewModel.GetSimilarCocktailsCommand.Execute(selectedCocktail);
Assert.AreEqual(sampleCocktails.Count, viewModel.SimilarCocktails.Count);
}
}
Astute readers will notice that because our ViewModel doesn't have a parameterless constructor we can't create it directly in xaml. This is correct, instead we'll be delegating the construction of the ViewModel to a Ninject kernel. We'll create a ServiceLocator that will be an Application Resource (in App.xaml), it will create the Ninject kernel and register the appropriate dependencies.
public class ServiceLocator
{
private readonly IKernel kernal;
public ServiceLocator()
{
kernal = new StandardKernel(new CocktailModule());
}
public CocktailsViewModel CocktailsViewModel
{
get
{
return kernal.Get<CocktailsViewModel>();
}
}
}
public class CocktailModule : StandardModule
{
public override void Load()
{
Bind<CocktailsViewModel>().ToSelf();
Bind<ICocktailService>().To<CocktailService>();
}
}
<Application.Resources>
<cx:ServiceLocator x:Key="ServiceLocator"/>
</Application.Resources>
For simplicities sake I have a simple module that will register the dependencies we need.
Unfortunately there's no nice GUI to hook the ViewModel up anymore we have to write our own Binding expression, but it's not too bad. This binds the DataContext of the UserControl to the property "CocktailsViewModel" which is in turn created by the Ninject kernal, injecting the appropriate dependencies.
DataContext="{Binding Path=CocktailsViewModel,Source={StaticResource ServiceLocator}}"
We're now back to where we were before but now with a unit tested view model. Later on I'll do a post on integration testing the entire stack.
