View/ViewModel Interaction - Bindings, Commands and Triggers

A discussion of how a View uses declarative XAML constructs like bindings, commands and triggers to interact with the properties, methods and events on its associated ViewModel. This goes into more depth around the concept I demonstrated at MIX10, and also demonstrates the latest additions to Silverlight.FX (as of v3.5).

It looks like I have a set of posts on ViewModel, aka MVVM, that have organically emerged into a series or story of sorts.


Recently, I blogged about The Case for ViewModel, and another on View/ViewModel Association using Convention and Configuration, and a long while back now, I posted an Introduction to the ViewModel Pattern as I was myself picking up this pattern, which has since become the natural way for me to program client applications. This installment adds to this on-going series. I've alluded to this topic in the past, but it is now time to focus and dedicate a post on the interactions between a view and its view model, i.e. the arrows in the diagram below:

The ViewModel Pattern

I like to present ViewModel as something that is not brand-new, but a simple refactoring of [most of the] code-behind into a separate class so that the logic is decoupled from the user interface. This class simply employs the basic OOP constructs that you might have encountered in CS101 - it encapsulates state and behavior, exposed via properties, methods and events.


As simple as properties, methods and events...

All view models will encapsulate some interesting application state or data, exposed as properties, usually, in an observable form, i.e. properties that raise change notifications. Almost all view models will also expose some operations, ideally exposed as vanilla methods. And finally, some view models will also raise application-specific notifications as events.


Declarative glue...

A view is then responsible for consuming and working against the object model exposed by its view model as it presents information, and collect and react to user input, gestures etc. The data-binding engine in Silverlight makes it natural to bind to the properties in one-way or two-way fashion. Commands (in the UI, not in the view model - will address this below) allow invoking operations, usually in response to some user input or external inputs (eg. a timer or GPS input). Finally triggers allow the view to listen to events and translate view model notifications into user interface actions. All of these serve as glue expressed in XAML via declarative markup.

This is captured in the diagram above. Bindings are fairly straightforward and you've more than likely used them if you've done any Silverlight programming. So I am mostly going to focus on commands and triggers, but first, lets see this pattern in action.


An example application...

Translation Application ScreenshotAs always, an example helps make things concrete. I converted Tim Heuer's translation/text-to-speech application to follow the view model. In doing so I used the latest release of Silverlight.FX - while the ViewModel is an abstract presentation, it is useful to pick up a framework that allows you to quickly get started with your application, rather than build the plumbing from scratch.

On the right is a screen shot of the application. It is also now included as part of a series of sample applications packaged with Silverlight.FX. You can dowload the latest version (v3.5) by visiting the project page. I'll have a Silverlight 4 version that takes advantage of new capabilities, but in the mean time the Silverlight 3 version should continue to work. The sample application here uses v2 of Microsoft Translator API, which now has support for not just translating text, but also converting text to speech for a specific set of languages. You'll need to get an API key and update the web.config in the sample on your end to run the application.

TranslateWindowModel Object Model

The class diagram of the view model highlights the interesting things going on in the view model:

In terms of application state, it exposes the text to be translated, the resulting translated text, the list of languages, and whether the speak operation can be performed. In terms of operations, it provides the ability to perform translation, or to speak (as in produce the audio stream) the translated text. Finally in terms of notifications, it lets its associated view know when that audio stream has been loaded and is available for playing.

Lets now look at the XAML:

<fxui:View
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  xmlns:fxui="clr-namespace:SilverlightFX.UserInterface;assembly=SilverlightFX"
  xmlns:local="clr-namespace:Translate"
  x:Class="Translate.TranslateWindow">
  
  <fxui:View.Resources>
    <fxui:Command x:Key="translateCommand" Method="Translate" />
    <fxui:Command x:Key="speakCommand" Method="Speak" />
  </fxui:View.Resources>

  <Grid>
    <fxui:VStackPanel Margin="10" ChildAlignment="Center" ChildSpacing="4">
      ...

      <TextBlock Style="{StaticResource labelText}"
        Text="Enter some text to translate:" />
      <TextBox x:Name="inputTextBox" Style="{StaticResource inputText}"
        AcceptsReturn="True" Width="400" Height="100"
        HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"
        Text="{Binding Text, Mode=TwoWay}" />

      <TextBlock Style="{StaticResource labelText}"
        Text="Select a language:" />
      <ComboBox Width="100" ItemsSource="{Binding Languages}"
        DisplayMemberPath="Name"
        fxui:Commands.Selection="{StaticResource translateCommand}" />

      <Border Style="{StaticResource displayArea}" Margin="0,10,0,0">
        <TextBlock x:Name="outputLabel" Style="{StaticResource labelText}" Width="400"
          Text="{Binding TranslatedText}" />
      </Border>
      
      <Button Width="100" Height="23"
        fxui:Commands.Click="{StaticResource speakCommand}"
        Content="Say It!" />
    </fxui:VStackPanel>

    <MediaElement x:Name="mediaPlayer" IsMuted="False" AutoPlay="True">
      <fxui:Interaction.Triggers>
        <fxui:ModelEventTrigger EventName="AudioStreamLoaded">
          <local:PlayWaveAudio />
        </fxui:ModelEventTrigger>
      </fxui:Interaction.Triggers>
    </MediaElement>
  </Grid>
</fxui:View>

The interesting bits are in bold. But first notice, what isn't there. The view doesn't need to say anything about its view model explicitly. The <fxui:View> class (which derives from UserControl) implements the convention as I described in my prior blog post, which causes TranslateWindowModel to automatically be created for the TranslateWindow view, and set as its Model as well as DataContext.


Bindings

You can see the Text property of inputTextBox and outputLabel bound to Text and TranslatedText properties of the view model using a XAML {Binding}, as you'd expect (mentioned here for completeness).


Commands

Now comes the interesting part. Generally, I've seen commands implemented in the view model using helpers like a DelegateCommand implementation. However this in my opinion adds noise to what ought to be a simple class with simple methods. I see commands as glue between the UI (events on controls) and operations (methods on view model), rather than state of the application to be exposed as properties on a view model. So in the example above I've declared some command instances in resources that the UI can use. Each <fxui:Command> object is a command which implements the standard ICommand interface, and is responsible for invoking the specified method. This is analogous to bindings which are responsible for retrieving or setting properties.

It is interesting to place a command in the resource if multiple events/controls can trigger the same command. A command can also be declared inline if its not meant to be shared (again just like binding). For example:

<Button>
  <fxui:Commands.Click>
    <fxui:Command Method="Speak" />
  </fxui:Commands.Click>
</Button>

And finally, once markup extension are enabled in Silverlight, I'd like to write (again, just like bindings):

<Button fxui:Commands.Click="{Command Speak}" />

By default <fxui:Command> executes a method it finds on its DataContext. However you can bind its Target property to any other object, such as another element within the view. Also, behind the scenes a command bound to the Speak method will look for the existence of a CanSpeak property on the same target object, and subscribe to property change notifications on that property, in order to accurately implement the CanExecute property of ICommand.

The other interesting thing going on here is the way commands are hooked up. I've used an attached property, Commands.Click - this is there for Silverlight 3 support where Button doesn't have an intrinsic Command property (which does exist in Silverlight 4). Additionally, I've applied the pattern to other scenarios - for example, I also implemented things like Commands.Selection that can be specified on any Selector-derived control such as ListBox or ComboBox. This allows invoking a view model operation when the selection changes. Folks have often asked why commands are just restricted to buttons and click events. They don't have to be.

Another interesting tidbit, by default, the selected item of the Selector is passed in as the command parameter, in case your view model operation works needs access to what was selected. So for the default case, you don't have to also specify the Commands.Parameter property. In the example above, the Translate method on the view model needs the selected Language and that just works.

And to where I am really going with commands as objects in the UI - you can attach behaviors to commands - eg. to perform pre and/or post logic. For example, I can have a Login behavior that automatically pops up a login dialog, allow the user to login if they click on a command that requires authentication, and upon successful login, let the command invoke the view model. Now the view model doesn't have to concern itself with interrupting its processing to show a login dialog, collect credentials etc.

I really see commands as a powerful building block in the world of XAML. I also demoed this approach in my MIX talk, so if you're looking for more samples, check out the post I did around the BookClub application from my MIX session.


Triggers

Sometimes a view model needs to raise notifications, that a view should handle and do something in response, esp. when these can't be modeled as properties and property change notifications.

For example, in the application here, the view model raises an event to indicate the audio stream for the translated text has been loaded. This could not be modeled as a property, since the MediaElement doesn't have a property of type MediaStreamSource. It instead has a method called SetSource. So something in the view needs to call that method.

Enter triggers and actions. The combination basically is a construct that lets you say, "when this happens, do that". In the code above I've attached a ModelEventTrigger to the MediaElement. The trigger listens to the Model, and subscribes to the specified event, AudioStreamLoaded. When that event is raised by the view model, the trigger invokes its action(s). In this case the PlayWaveAudio action is invoked, which receives the audio stream from the event, creates a MediaStreamSource after parsing the wav data returned from the translation service, and calls on the associated MediaElement's SetSource method to play the audible version of the translated text.


Summary

The core view model pattern is simple - it is all about authoring a vanilla class that encapsulates what is interesting in your application, and then consuming that via declarative building blocks in XAML.

For more view model reading, I also have posts on implementing modal dialog scenarios and MVC-based navigation in conjunction with the view model. And I am sure I'll have a few more view model posts over time, so stay tuned, and as always, do share thoughts, comments, suggestions and questions below.

Posted on Wednesday, 3/24/2010 @ 12:12 AM | #Silverlight


Comments

14 comments have been posted.

Anoop Madhusudanan

Posted on 3/24/2010 @ 1:15 AM
Nikhil, I liked the approach about representing commands as objects in the UI itself, and way the way you are hooking up to the view model methods directly (instead of ICommands).

Just want to point out that I tried something similiar, for Invoking methods in VM directly, by implementing an 'InvokeMethodAction' using System.Windows.Interactivity - with support for mulitple action parameters, so that it'll invoke a method in the View Model when ever a named event is triggered. http://amazedsaint.blogspot.com/2009/12/slex-for-silverlight-preview-2.html.

Your implementation looks very clean. Realized that a convention based approach in various scenarios can save a lot of code.

Stuart Allen

Posted on 3/24/2010 @ 6:32 AM
As a newbie to the world of MVVM, I appreciate your articles on this subject.

There really needs to be a unified way to do this type of programming across WPF and Silverlight. I've learned PRISM, now it appears I need to learn .FX, when will there be more convergence in this space?

Love your content Nik!

Michael L Perry

Posted on 3/24/2010 @ 6:37 AM
I'm more interested in the relationship between the View Model and the Data Model. Could you expand the Fields section in TranslateWindowModel? I keep clicking on the plus but nothing's happening.

Nikhil Kothari

Posted on 3/24/2010 @ 8:08 AM
@Anoop
Commanding doesn't replace actions - Silverlight.FX supports actions for those who like that approach as well. I've traditionally used that - for example
<Button fxui:ClickAction="$model.Translate(languageDropDown.SelectedItem)" />
which is a shortcut for specifying an Invoke action for a Click trigger.

Commands are a bit more designable in the tools, than the little expression syntax that comes with actions.

@Michael
The interaction between view model and underlying data model will differ based on what the data model is. If you look at the samples in Silverlight.FX you'll see a variety of services - amazon, new york times, etc. and now translation APIs. I've also separately shown view model + ria services. Each is a bit different ... what is common is the view model encapsulates the service calls so they are completely hidden from the view. Also common is the async data access, given this is Silvelight, and only async network requests are possible. So the view model calls async APIs, and when the data is available, raises change notifications to cause the view to update. The view model does expose the entities to the view directly.

In this sample for example, there is a Translator object, that represents the translation APIs. It has a GetLanguages method that returns an IEnumerable<Language> result. This result is exposed to the UI, and bound into the dropdown. So the Language object, i.e. the entity is exposed to the view.

Hope that helps.

Vaibhav Deshpande

Posted on 3/24/2010 @ 12:41 PM
Nice article. Some of things that I think are used more frequently in an app is switching a region in a view based on a condition, printing, context menus... Unless there is a way around, I am going to have to use code behind as they are view-specific. If I have to use code-behind, I can use event handlers and call methods of my ViewModel directly, eliminating the need for any framework (Binding will handle the state of the ViewModel and operations are handled by code-behind). Can you please share your thoughts on this.

Nikhil Kothari

Posted on 3/24/2010 @ 2:52 PM
@Vaibhav

You can easily get things like conditional visibility through bindings. A number of other scenarios can be addressed by code-behind qualify for evaluating whether they can be packaged into reusable behaviors that form a useful toolkit of components that are easy to declaratively include into the view.

Joseph Hemingway

Posted on 3/24/2010 @ 11:00 PM
I have been enjoying these articles as I have an upcoming project that I intend to implement in Silvernight, this will be my first Silverlight project and I intent to use the MVVM pattern.

I however don't like the idea of setting up the bindings etc in xaml. In fact I don't even like setting the UI element's event handlers in xaml. I would prefer to do this in the code behind and have xaml only responsible for presentation. I would prefer to have all bindings to the ViewModel and UI events declared in the code behind.

This way I can break the view up into:
- presentation (xaml)
- viewModel interaction and UI events (code behind)

You seem to want to declare as much as possible in xaml and put as little as possible into the code behind. I would love to get your thoughts on the pros and cons of each approach? Would you recomend against my approach and if so why?

Anoop Madhusudanan

Posted on 3/25/2010 @ 12:05 AM
@Nikhil Understood the point. Will check out actions in Silverlight FX .

In the Slex implementation, I've a way of passing parameters to methods via actions in a 'blendable' (no expression syntax) way. But it is heavy.

<EventTrigger ElementName="btnTranslate" EventName="Click">
<InvokeMethodAction MethodName="Translate">
<ActionParameter ElementName="languageDropDown" Property="SelectedItem"/>
</InvokeMethodAction>
</EventTrigger>

@Vaibhav About conditional invocation of Actions - I've a way here to for conditionally invoking actions and commands. http://amazedsaint.blogspot.com/2009/12/slex-for-silverlight-preview-2.html

Nikhil Kothari

Posted on 3/25/2010 @ 12:24 AM
@Joseph
Ultimately XAML is code - it is an xml syntax for declaring object instances and initializing them.

Even if you move your bindings into code, they are still just as late-bound (eg. property paths are strings), so putting them in c# syntax as opposed to xml syntax doesn't buy much in terms of early/static binding if thats what you're after.

On the flip side, I think defining bindings etc. is a pain in c# - you have to FindElement the right element to have a reference (more strings, as well as x:Name declarations in xaml which I try to avoid), before you can add the binding to the element. Furthermore, this style of FindElement might work for top-level elements, its multiple orders of magnitude harder to FindElements inside a template - you have to hook into template instance creation.

My suggestion - get over it, and define things in XAML, i.e. use the capabilities of XAML, rather than use XAML, but without using its full potential. However, that is my personal opinion :-)


@Anoop
I guess you get to decide - verbose syntax with blendability or a more reasonable expression syntax with a little less blendability (actually if I had the time to build a design-time experience, I believe those expressions could be also tooled as well). I personally like to type most of my XAML, and even if I didn't type it in, I still have to read my XAML, and prefer less verbose markup, as its easier on the eyes. Again, thats personal opinion and preferences...

Btw, the fxui:Interaction.Action is shortcut for an EventTrigger bound to the Click event with an InvokeScript action. The long form, for arbitrary actions/events is the same as what you have, which is also supported in Silverlight.FX.

Sanjin

Posted on 3/25/2010 @ 12:43 AM
Interesting article :). Where can I download the example?

Nikhil Kothari

Posted on 3/25/2010 @ 1:56 AM
@Sanjin
Download Silverlight.FX at http://projects.nikhilk.net/SilverlightFX and look at the Translate sample within the samples folder.

Daniel Calbet

Posted on 3/26/2010 @ 12:19 PM
First of all, thanks a lot for sharing you work. And as you say in the answers at the end is all a question of personal preferences.

Said that, I have the following objections:
1) I prefer to use XAML versus C# code separation to differentiate presentation and functionality code.
2) I personally prefer the approach used here:

http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2009/11/18/silverlight-4-rough-notes-commanding.aspx

http://johnpapa.net/silverlight/5-simple-steps-to-commanding-in-silverlight/

But note that in those articles they don't use any framework. They show all the code they need.

3) as you use binding by convention, really the comparison has to be with the approach showed here (using Caliburn framework).

http://devlicio.us/blogs/christopher_bennage/archive/2010/03/03/1-simple-step-for-commanding-in-silverlight.aspx

Nikhil Kothari

Posted on 3/26/2010 @ 1:09 PM
@Daniel
My personal belief is one shouldn't have to replicate boiler plate code, and instead focus on their application - hence frameworks are useful. Of course frameworks should be minimal, simple etc. and a pleasure to work with.

On commanding specifically, I personally disagree with polluting my view models with ICommand members, initialization, properties etc.

I am only binding the view to its view model by convention. I am not binding to properties, commands etc. by convention.

Vaibhav Deshpande

Posted on 3/27/2010 @ 3:14 PM
Thanks Nikhil and Anoop for sharing your thoughts. We just finished up writing a business app in Silverlight 3. We used MVVM and IOC principles for our app. We used Regions from CAL(Prism) and MEF to help us with our app. During our testing phase we found out that our app had memory leaks. I used windbg/sos to find out memory leaks and turns out that both regions and MEF(in certian cases) was holding up our views and viewmodels. I understand that these frameworks are new and still evolving but dealing with issues from the framework are no fun either. Its great to see the different ideas that people are coming up with however one has to be cautious while using them.
Post your comment and continue the discussion.