Designer / Developer Workflow, Part 1: Building RIAs with Silverlight
Author : Richard Griffin – Conchango
This article appeared in the Expression Newsletter;
subscribe to get the next issue.
In this article and the following articles we will show you how to build a RIA using Silverlight; illustrate the workflow between designer and developer; and also how to get the most out of the tools that you have been using for years and some tools that you may have not heard of before or just started out using them. The application that we are going to build over the course of this series articles will use the del.icio.us social bookmarking api. If you have not heard of del.icio.us then I would strongly recommend that you go and check it out as a serious life hack that will improve your ability to manage your bookmarks. For me it has two main positives; Firstly I use a number of different machines and this means that I end up surfing the internet from a variety of PCs and remembering the url to a site I found on another machine was all too painful, this is no longer the case with del.icio.us; Secondly it has a great social network that allows me to share bookmarks with other people who are interested in the same topics.
Del.icio.us has a simple api that you can call which returns the requested data as xml. Originally netlicous was designed and built by 0 by Nate Zobrist as a windows forms client. The application was a simple and effective way to provide del.icio.us users with the ability to view bookmarks ordered by tags, or as a list of posts or user created bundles directly on your desktop without the need to fire up a browser window and navigate to your del.icio.us home page. The application is ideal for illustrating how we can use Silverlight to build a RIA that will run in the browser and leverage the user persistence storage as well as an example of how to leveraging the cloud to provide the data that the application requires to be functional.
For the purposes of this example we are going to assume that the design of the application is the same as the original netlicious design and that we are being requested to build a RIA version in Silverlight. As the developer my first job is to create the Visual Studio solution that we are going to use and to create the structure of the architecture that will be used. Not only is my primary task to get data from the cloud into the presentation layers, it is also to create and implement a presentation pattern that allows the separation of concerns between myself and Felix who is going to be implementing the UI design. By following these patterns can provide an architecture that allows data to be rendered in Blend and thus provide a pseudo runtime look and feel of the controls that the designer needs to create. One of the problems that we have faced in the past is that although the Xaml my render correctly at runtime however it is not always visible in Blend and unfortunately causes Blend to throw an exception. This can be caused when the UI is tightly coupled to business objects and services that are not available during design time. One of the additional tasks that face UI developers is that they must provide a design time version of the application in order for designers to be more productive. With the new versions of Blend UI developers will be able to provide Xml data model representations that will allow designers to have a design time version.
Passive View pattern (created by
Martin Fowler), may seem to be a developer focused task however, the designer should be aware of how the presentation layer has been constructed, a better understanding of the pattern will help with designers on a number of levels; first when communicating with the developer a better understanding will enhance communication; second when creating User Controls or styles and templates for templated controls they have a better understanding behind the motivations of why a particular structure is being implemented. I am sure that most designers don’t have a great interest in software architectures however gaining a better understanding from a high level will enhance the workflow between the designer and developer. This is also the case with regards to developers that need to build a better understanding about design and User Experience.
Silverlight and WPF lend themselves to the Passive View pattern that helps enforce the separation of concerns and single responsibility for components that we are looking for in the architecture. One of the outcomes of using this pattern is that testing the components can be done easily. So there are a number of benefits in using the pattern but how difficult is it to implement, from the prospective of a UI developer that may have not used the pattern before? There is a great tool that can be used called Ninject from Nate Kohari who has built a simple dependency injection framework.
Dependency Injection (DI) is a way to help enforce the single responsibility that we want to use in the application and it is also a mechanism that allows the Passive View pattern to be used effectively in the application. You can read more about DI here. DI provides the ability to create loosely coupled and highly cohesive components. Now that we have covered off some the basic principles that we are going to use in the application it’s time to create the application architecture and the right references, a quick note on references, as a general rule I favour adding all referenced assemblies that are external to the framework into a folder called Lib that is included in the root directory of the application. So if you haven’t already fire up visual studio and create a new Silverlight application and ensure that you select the option to create a web project to host your Silverlight application. We could use the dynamic option however; we want to use a test html page that will run our tests that we will cover off later in the series.
Once the Silverlight application solution has been created in Visual Studio we need to create the other Silverlight projects that are going to be used in the solution. First create the delicious core project that will contain all the data model classes and the wrappers around the delicious Api calls that we are going to use. Add a new Silverlight Class Library to the solution called Delicious.To get the layout that we require for the Tag Cloud which is going to be the first UI elements that we build, I am going to use Dave Reylea’s Animated Wrap Panel. This can be done by adding the project into the existing solution. I also created a Silverlight test project using the Silverlight templates from Dave Wilcox, which we will cover off in a future article. Once the projects that we need for the application have been added the solution and project structure should look something like this.
Let’s take a minute to review what we have done as there are a number of projects that have been added.
- Animated Wrap Panel is going to provide the Layout of the tag cloud UI elements.
- Delicious is the core project that provides the data model and services.
- Delicious.Test will contain all our test code.
- DeliciousSilverlight is where all our UI Xaml elements will live.
- DeliciousSilverlightWeb is the web project that holds the Silverlight object in our html page.
Now that all the composite parts have been added the UI delicious Silverlight project needs to reference the projects and assemblies that we are going to use so our next task is to add the references. Right click on the DeliciousSilverlight project and add references to the Animating Wrap Panel, Delicious core project and Ninject core assemblies. We also need to add a reference to the System.Xml.Linq assembly. Now that the UI project has all the references we can add our Module class and Service Locator class that will provide the building blocks for implementing the Passive View pattern that we talked about earlier. The Module class is required by
Ninject and also provides the ability for the developer to allow the designer to have sample data when using Blend to change the UI elements with test data bound to the controls at design time. For more information about Modules and Kernel see here.
The code above is all that is required for the module of the application, which provides the application with how we are going to wire up the services and the corresponding view models used in the application. Here you can see that we are binding the Post Service and its corresponding View Model and the same applies to the Tag Service. There are two other important parts to grok; first notice that we are going to inject the service into the View Model which provides the the loosely coupled and highly cohesive components that we are looking to build; second to note is that we are injecting the proxy string into the Post and Tag Service implementation classes and we are only going to execute this code if the application is running in the browser. Once we have this code in place then we need to build the View Model classes for each view. A view is classified as a User Control and my preferred naming convention is to add View on the end of all User Controls this helps to clarify what the controls are that you are looking at easily. Each View has a corresponding View Model, for example TagView and TagViewModel provides a quick and easy way to know which views are related to which view models.
Next we need to create the view models that are required to power the data in the views. The view model’s all implement INotifyPropertyChanged. The INotifyPropertyChanged interface means that we can use built in notifications to inform the view when the data changes by binding the view’s data context directly to the view model. This simple techniques means that the view is always in sync with the data returned from the service. The structure of view model class is such that it presents the data required by the view its other responsibility is to call out to the service and request data.
The code above illustrates the constructor of the view model and it’s important to notice that we have decorated the constructor with the Ninject’s Inject attribute that means we can inject a concrete implementation of a class that implements the correct interface type. The design means we have the ability to pass in either mock or a real class that is of the correct type. You can also see that inside the constructor there is a call out to the get the tags from the tag service. Now that the view model is built the next task is to wire the view to the view model.
Let’s start with the code behind the view, this next task requires that we wire up the Animated Wrap Panel with the animation required and also wire up to the PropertyChanged event handler provided by the view model that will inform the view when there is a change to the data displayed in the UI. First we add in the property for the data context which provides the view with a reference to the view model. We will talk more about this shortly when we take a look at the Xaml. Inside the constructor of the view we can added in a condition that will detect if the view is running inside of Blend. The DesignerProperties call is very useful in order to allow the views to be used at design time by the designer. Next we need to inform the animated wrap panel about the duration for the animation and also the type of animation that we want to use. Inside the property changed event handler we need to manually find out which property in the view model has changed, in this particular case the view is only interested in the collection of tags. If the tags collection has changed then we iterate over the collection and create a TextBlock UI element to represent the tags by setting the text to be the name of the tag and we also set the FontSize to equal the count. So we have finally arrived at the view, it has take a little time to get up through the layers but organising the components this way has many advantages that we have noted earlier. The main point to note in the view is the DataContext, here we are binding the data context to the view model. Normally we would do this to take advantage of the powerful databinding that Silverlight provides. I also wrapped up the animated wrap panel with a scroll viewer allowing the user to view a large number of tags. The final result can be seen below. The animated wrap panel means that we get the right layout of the tags when we resize the browser window, it also means that we get a nice animation when we do this. We have covered a lot of ground in this first article, from my experiences working on client projects the first steps are taken by the developer and this article illustrates the goals that the UI developer should be aiming for. Not only are we building an application that is testable but also one that has a solid architecture which consists of loosely coupled and highly cohesive components ready for the designer to start work. We also have to ensure that the views we introduce into the architecture can be viewed at design time in Blend, this can be easier than it sounds.
In the next article, we will start to create a GUI that is closer to the actual design. This is the time when we start to experience the benefits of the designer being a first class citizen in what was a developer orientated world, their ability to use tools that are directly manipulating the files we are working on has its advantages and disadvantages.