Fluent Silverlight – Part 1

Introduction

We (that is Ray Houston and myself) want to introduce a new framework we developed in the past few months. This framework provides a fluent interface to Microsoft Silverlight. As we have been able to leverage a lot of OSS software in the past we found that it is time to give something back to the community too. This was the birth of the OSS project we call “Fluent Silverlight”. The code is publicly available and is hosted by Google Code. It can be found here.

Motivation

This past year our company developed a Silverlight client for our .NET web application. The Silverlight code base has grown quite large and we’ve started trying to improve some of our biggest pain points. One of the biggest that we’ve faced, is our implementation Model-View-Presenter (MVP). We ended up with a lot of "ping-pong" communication between the view and the presenter.

We had a lot of code that:

  • An event would happen on the view,
  • be handled in the “code behind” of the view and tell the presenter,
  • the presenter would make a decision and may tell the view to do something else
  • possibily repeat the whole cycle.

We tried creating tests, but they only really tested interactions and didn’t test the true intent of the view. They only verified that "yes, we have an implementation" and did not test that the view was working as a whole. We didn’t feel as if we were getting a good return on investment with the MVP tests, so we ultimately stopped writing them
and just relied on integration tests to check the functionality.

As we began to trust data binding in Silverlight (we had been burned in the past and we did not have any prior WCF experience), we started to look at Model-View-View Model (MVVM) as an alternative. We really like the strongly-type declarative style of Fluent NHibernate and FuBu MVC, so we tried to see if we could do something similar with
Silverlight and MVVM.

Fluent Silverlight is an attempt to make MVVM easier by using a fluent interface with strongly-typed reflection to define controls and bindings and avoid the XAML based "wiring" of the view to the view model. It hides the implementation details so that they are allowed to change without changing the view  or the view models they are bound to. An example would be the way it hides the ugly event handlers and allows you to associate controls events directly to commands on the model.

This will be a multi-part post series. In this first part we want to introduce some of the basic concepts of our new framework. Especially we want to show how a user control can be bound to a view model.

The Model-View-View Model Pattern

The model-view-view model pattern (MVVM) is often used when building WPF or Silverlight applications. We decided to use it as the primary pattern in our framework. The MVVM pattern is a variant of the MVP pattern. A good introduction into the MVVM can be found here.

The view model

The view binds to properties on a ViewModel, which, in turn, exposes data contained in model objects and other state specific to the view. The bindings between view and ViewModel are simple to construct because a ViewModel object is set as the DataContext of a view. If property values in the ViewModel change, those new values automatically propagate to the view via data binding.

The view model contains all the data a view needs for display. A view model in contradiction to a domain model can also expose display relevant properties. Examples of such properties are whether the content of e.g. UserName should be read only or not or whether a specific control displaying the content of a property should be visible or not in a certain context.

But the view model is not only a data container. Since it is a variant of a presenter it also contains behavior. It coordinates between the view, the (domain) model and the (backend-) services. As an important example it exposes commands that can be bound to an event of a control on the view.

Since data binding is used to update the controls on the view the view model must implement the INotifyPropertyChanged interface. Since every view model has to do this and since we wanted to keep or code DRY we decided to define a base view model class from which all other view models have to inherit.

Properties

We have been able to build an infrastructure such as that our ViewModel is very slick. Although we implement the INotifyPropertyChanged interface to make data binding possible we only need to implement each property as auto property in our ViewModel. Normally when implementing the said interface the code of a property looks similar to this

private string userName;
public string UserName
{
    get { return userName; }
    set
    {
        if(value == userName) return;
        userName = value;
        PropertyChanged("UserName");
    }
}

in our framework we have reduced this to

public string UserName { get; set; }

which we think is a significant improvement. The technique we use to make this possible is interception. Basically we wrap the view model with a proxy. This technique will be described in details in an upcoming post of Ray.

Commands

To define a command in the ViewModel to which an event of a control can be bound we use so called DelegateCommands.

public DelegateCommand<object> SaveCommand;

A delegate command usually is instantiated in the constructor of the view model and requires two methods delegates when instantiated. The first one is a delegate to the method that is called when the command is invoked through the user action. The second one is a delegate to a method which determines whether the command is available in the given context or not. The first delegate is mandatory whereas the second one is optional.

public SampleViewModel(...)
{
    ...
    SaveCommand = new DelegateCommand<object>(OnSave, CanSave);
    ...
}

By the way: the DelegateCommand has been introduced in the Microsoft Prism framework. We have slightly modified it to adapt it to our specific needs.

The controls bound to a command will be automatically enabled or disabled if the command is available or not.

The view model is an important cornerstone in our framework. We have provided it with many useful features such as that it merits it’s own post. The view model will be described in details in our next post.

Fluently bind existing XAML user controls to a view model

Imagine having loads of Silverlight user controls that are written in XAML. You want to leverage these controls without having to port them right away and use a fluent API to bind these controls to a view model.

Bind to a property

Lets assume that on the user control we have a TextBox called txtUsername. We want to bind the Text property of this TextBox to the property UserName of the view model. The syntax we would like to use to accomplish this binding is as follows

this.WithTextBox(txtUsername)
    .Text(m => m.UserName)

The binding is described with the aid of a lambda expression m => m.UserName in this case. I took the parameter m as it is an acronym for model. If you are not familiar with lambda expressions please refer to this post for a detailed introduction into delegates and lambda expressions.

The WithTextBox function is an extension method of the UserControl and takes as an argument the element which we want to bind to our view model.

But that’s not all. We want as well bind the IsReadOnly property of the same TextBox to the property UserNameIsReadOnly of the view model. Further more we want to bind the properties Visibility and Enabled to the corresponding model properties. Thus our code now should look similar to this

this.WithTextBox(txtUsername)
    .Text(m => m.UserName)
    .IsReadOnly(m => m.UserNameIsReadOnly)
    .IsVisible(m => m.UserNameIsVisible)
    .IsEnabled(m => m.UserNameIsEnabled)

There is one important fact that I want to discuss here. Each FrameworkElement has a property Visibility which determines whether the corresponding control is visible or not. Unfortunately the Visibility is not a boolean but an enum although there exist only two possible states namely visible and collapsed. Since our view model should not contain any display specific logic we do not want to have properties of type Visibility in our view model but rather just use a boolean for properties concerning the visibility of a control. Fortunately Silverlight (as well as WPF of course) offer the possibility of so called value converters that one can use when binding a property of a control to a property of a model. We will make use of this possibility and write our own VisibilityToBoolean converter.

The above syntax look really nice and the code is fully type safe. If you have to refactor the view model and e.g. rename a bound property a tool like Resharper will automatically rename/refactor the above code for you too. Furthermore we can profit of full intellisense support.

Bind to a command

We do not only want to bind certain properties of our Silverlight controls to the view model but we also want to be able to bind events to specific commands defined in the view model. Most of the time this will be the Click-event of controls derived from the ButtonBase control such as a Button or a Hyperlink control. The syntax we want to use should be similar to this one

this.WithButton(btnCancel)
        .OnClick(m => m.CancelCommand);

Again the binding of the event to the command in the view model is expressed with the aid of a lambda expression.

As soon as a user clicks the cancel button the CancelCommand defined in the view model is executed. No need to implement any further code in the view! Our view stays perfectly humble as desired.

Furthermore a command can or cannot be executed in a given context. This fact is determined by some business logic. If a command is not executable at the moment then the Silverlight controls bound to this control are automatically disabled.

Fluently create and bind a user control

If we can start from scratch and create a new user control then we can do this by using the new fluent API. As an example we want to define a user control which contains a stack panel with some text blocks and some text boxes. Also there are two buttons save and cancel. In our user control (=view) we have an initialize method where we put the code to create the layout

public override void Initialize()
{
    var grid = this.GridFor("Grid1")
        .Background(Colors.Cyan)
        .Margin(3, 10, 3, 5);
 
    var stackPanel = this.StackPanelFor()
        .Orientation.Vertical()
        .Margin(4)
        .AddChild(this.TextBlockFor("Book Title:"))
        .AddChild(this.TextBoxFor(m => m.BookTitle))
        .AddChild(this.TextBlockFor("Book Author:"))
        .AddChild(this.TextBoxFor(m => m.Author)
                      .FontWeight.Bold()
                      .FontStyle.Italic())
        .AddChild(this.TextBlockFor("Publisher Name:"))
        .AddChild(this.TextBoxFor(m => m.PublisherName)
                      .ReadOnly())
        .AddChild(this.TextBlockFor("Price:")
                      .FontWeight.ExtraBlack()
                      .Cursor.Hand())
        .AddChild(this.TextBoxFor(m => m.Price)
                      .Width(80)
                      .HorizontalAlignment.Left())
        .AddChild(this.StackPanelFor()
                      .Orientation.Horizontal()
                      .AddChild(this.Button("Save")
                                    .Width(70)
                                    .OnClick(m => m.SaveCommand))
                      .AddChild(this.Button("Cancel")
                                    .Width(70)
                                    .OnClick(m => m.CancelCommand)
                      )
        );
 
    grid.AddChild(stackPanel);
 
    Content = grid;
}

Usually this is the only code that is needed in a view. And as a result our view remains really humble. Please note as well that the only strings that are still present in the code are labels. Every thing else is strongly typed.

The above code does show some of the possibilities the framework offers. Layout elements as font styles, cursors, alignment or size can be set. Specific properties of controls can be bound to properties of the view model and the click event of button type controls can be bound to commands also defined in the view model.

We can even apply predefined templates to any control or a watermark to a text box as shown in the following sample

public override void Initialize()
{
    plainText = this.TextBoxFor(m => m.TextAnswer)
        .Interactable(m => m.TextAnswerInteractable)
        .Visible(m => m.TextAnswerVisible)
        .Template("textBoxTemplate")
        .Apply(TextBoxStyles.GetStandardFontStyles())
        .Watermark("Enter an answer please")
        .VerticalAlignment.Top()
        .HorizontalAlignment.Stretch();
 
    Content = plainText;
}

A watermark is a text that is displayed in a textbox if the corresponding textbox is empty and does not own the focus. Often the watermark text is displayed in a different font style and/or color that normal text (e.g. in gray).

Code

The project is called fluent-silverlight is hosted on Google Code. You can find it here. Feel free to browse and/or download the code and experiment with it. Any constructive feedback is highly appreciated.

Summary

In this post we have introduced a new OSS framework which provides an alternative way to implement a Silverlight application. The framework is built with TDD in mind and is meant to lead to scalable, maintainable and flexible applications. Views shall be as humble as possible since they are the only parts of the application that cannot be tested in isolation. All the presentation logic is implemented in the view model. Data and command binding is used between view and view model.

This framework is used in our internal application. We are still in a discovery phase. Many parts may change in the near future as we progress. Never the less we feel that it is worth to share our ideas with the community.

This post is the first part of a whole series of articles that will be published soon.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Gabriel Schenker

Gabriel N. Schenker started his career as a physicist. Following his passion and interest in stars and the universe he chose to write his Ph.D. thesis in astrophysics. Soon after this he dedicated all his time to his second passion, writing and architecting software. Gabriel has since been working for over 12 years as an independent consultant, trainer, and mentor mainly on the .NET platform. He is currently working as chief software architect in a mid-size US company based in Austin TX providing software and services to the pharmaceutical industry as well as to many well-known hospitals and universities throughout the US and in many other countries around the world. Gabriel is passionate about software development and tries to make the life of developers easier by providing guidelines and frameworks to reduce friction in the software development process. Gabriel is married and father of four children and during his spare time likes hiking in the mountains, cooking and reading.
This entry was posted in fluent Silverlight, introduction, lambda expressions, patterns, practices, reflection. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://michaelsync.net Michael Sync

    Hi Ray,

    I love the idea of using Interception for INPC. I’m thinking to do the same with Unity for our Prism v2 project as well.

    I got one questions. Why do we have to use WIthTextbox or etc? I prefer not to use the code-behind file. I love Binding and Command without having any code-behind. :)

    this.WithTextBox(txtUsername)
    .Text(m => m.UserName)

  • http://www.lostechies.com/members/gnschenker/default.aspx Gabriel N. Schenker

    @Michael: I will forward your question to Ray ;-) … but seriously: how would you define the binding or a (existing XAML based) view to the view model if not in the code behind? Of course you could define the binding in the XAML but this is exactly what we want to avoid. Ultimately we want to define most of our controls without using XAML at all (except for templating).

  • http://krishnabhargav.blogspot.com Krishna

    Love the idea…especially the properties one. But I am not personally attracted to the databinding in code. I think all the nice tooling features with blend/vs would go in vain….again not an expert and I appreciate your effort for the community.

  • Sandor Davidhazi

    I’ve been working on a LOB Silverlight application using the MVVM pattern and I can sincerely say that if this framework works as advertised here, it will revolutionize implementing the MVVM pattern.

    Some notes and questions:

    1. I don’t think that defining an interface layout should be done in the code behind. Blend works with the xaml file, and also does Visual Studio, but they won’t be able to work with properties that were set in the code-behind.

    2. I didn’t understand why people insist on defining everything in xaml, and celebrate that with commands they can implement event handling in the code-behind. I don’t think a designer has anything to do with implementing functionality, and he would never mess with rewiring a usercontrol’s events to commands.
    Your whole idea of placing binding logic into the code behind just feels right! Not to mention how awesome it is to use a well designed fluent interface, and strong variable references to do that!

    3. Can you pass parameters to commands?

    4. How do you define the converter for the bindings?

    I’m really looking forward for the coming posts, because MVVM development in Silverlight is really a PITA. Everybody is hyping the MVVM pattern, but really when it comes down to implementing it in a real-world, complex application, you have to face serious limitations and writing messy code. It just isn’t fun.

  • http://www.lostechies.com/members/gnschenker/default.aspx Gabriel N. Schenker

    @Sandor: we do not use tools like Blend to design our UI. We have a very specific UI which is hierarchical and highly dynamic – not the UI that those tools are made for. This is the reason why for us XAML has (nearly) no advanatages but only the known disadvatages (not wrist friendly, not strongly typed, etc.)

  • http://www.merill.net Merill Fernando

    Cool. This is excellent stuff.

    One warning though, if one of the goals of using WPF/Silverlight was to have designer’s own the UI and for the devs to own the business logic you should be careful about what you put in the code. For example the changing the label above would require a code change whereas if it were in xaml the designer could change it themselves.

    Another example is if the the designers wanted to change the commands from being a command button to a drop-down menu or some other control, they wouldn’t be able to in this instance.

  • Fabian

    How do you guys deal with validations, by validations I refer to checks that need to be performed so the view does not let something happen that should be be. e.g. user wants to enter a end date that is less than the start date. Obviously we might not want to have this validation in the View. Then a choice would be the View Model, but then how would the View Model react and notify the Presenter or View on what the problem is? That seems to be a very tricky set of actions and responses.

    Thanks

  • http://www.lostechies.com/members/gnschenker/default.aspx Gabriel N. Schenker

    @Fabian: validation is a concern we have not adressed so far but it is definitely on our pending list. But with our approach of data binding we are certainly on safe grounds and we will be able to extend the framework to include validation

  • John

    Nice

  • Ross

    Any chance that you’ll be adding support for other controls soon…like ComboBox?

  • http://www.vinfotech.com/ Ashish

    Nice articles, thanks.