Mike Taulty's Blog
Bits and Bytes from Microsoft UK
Silverlight 4, Blend 4, MVVM, Binding, DependencyObject

Blogs

Mike Taulty's Blog

Elsewhere

Archives

I was thinking about an aspect of the new MVVM support that Expression Blend 4 has and how ( I think – someone can tell me if I’m wrong ) it all starts with a seemingly small change in data-binding in Silverlight.

If I take a ViewModel like this into Expression Blend 4;

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using Microsoft.Expression.Interactivity.Core;

namespace MvvmApplication2
{
	public class MainViewModel 
	{		
			public ICommand MessageBoxCommand
			{
				get
				{
					if (this.messageBoxCommand == null)
					{
						this.messageBoxCommand = new ActionCommand(parameter =>
						{
							MessageBox.Show(string.Format("Parameter was {0}", parameter), null, MessageBoxButton.OK);
						});
					}
					return(this.messageBoxCommand);
				}
			}
			ICommand messageBoxCommand;
	}
}

and we set the ViewModel as the DataContext for a view then I can use the Data window in Blend in order to create “sample data” around it;

image

which then gives me a view such as;

image

and it’s cool because I can then create some piece of UI like this below where I have a Shape and a TextBox ( it’s just for example purposes here );

image

and I can then drag my MessageBoxCommand from my Data window in Blend over to that Shape and Blend will automatically “know” that what I want to do is invoke that command when something happens on that shape;

image

and what it does is generate an InvokeCommandAction and ties that to a Trigger on that Shape and the Trigger by default will sync up to the MouseLeftButtonDown event on the shape but it could equally be any other event and it certainly doesn’t have to have anything to do with a Click handler because ( AFAIK ) the Shape doesn’t even have one.

This allows me to be nice and declarative in my View and yet still bind to functionality on my ViewModel like my MessageBoxCommand. As an aside, if I didn’t have an ICommand property on my ViewModel but, instead, had a plain old method then Blend would do the right thing because it also has a CallMethodAction which can invoke a method on the DataContext ( in my case, the ViewModel ).

And so Blend preserves that View<->ViewModel separation for me using the triggers/actions/behaviors that began in Expression Blend 3.

My MessageBoxCommand took a parameter though and Blend provides for that too. I can go and grab that parameter in the properties window;

image

and bind it over to the Text property on my TextBox just by dragging and dropping ( note – I’m not saying that you would actually do this but it works for this example of getting a command parameter through to my command ).

Now, that’s kind of interesting because what Blend then generates is this lump of XAML;

		<ed:Callout>
			<i:Interaction.Triggers>
				<i:EventTrigger EventName="MouseLeftButtonDown">
					<i:InvokeCommandAction 
						Command="{Binding MessageBoxCommand}" 
					CommandParameter="{Binding Text, ElementName=textBox}"/>
				</i:EventTrigger>
			</i:Interaction.Triggers>
		</ed:Callout>

where you’ll notice that the InvokeCommandAction has its properties Command and CommandParameter databound to the respective properties on the ViewModel and the TextBox.

Now, in Silverlight 3 I don’t think this would have been possible because InvokeCommandAction derives from DependencyObject and, in Silverlight 3, you can’t have a target of a data-binding which is a DependencyObject – you have to derive from FrameworkElement and that wouldn’t really be right for InvokeCommandAction.

However…in Silverlight 4 you can have objects which are the target of bindings as long as they derive from DependencyObject and so ( for me ) what seems a little tiny change where the base class for the target of bindings moves from FrameworkElement to DependencyObject is what allows a designer to sit in Blend and nicely drag/drop my ICommand to the View and have Blend do the right thing.

Neat.

If you want to see more on this kind of thing in Blend 4 then I can strongly recommend this session from MIX the other week – it certainly got me thinking/playing with this stuff.


Posted Sat, Mar 27 2010 11:46 PM by mtaulty
Filed under: , ,

Comments

shaggygi wrote re: Silverlight 4, Blend 4, MVVM, Binding, DependencyObject
on Sun, Mar 28 2010 4:24 AM

Thanks for the info.  I was just playing around with how to add the InvokeCommandAction.

I noticed when you create a basic Method in the ViewModel and it returns something and/or has arguments, it will not recognize it in the Data tab.  Do you know if they plan on adding this ability in Blend 4 RTM?

What is the difference between using InvokeCommandAction and CallMethodAction?  Seems like it could do the same thing.

Thanks again.

Laurent wrote re: Silverlight 4, Blend 4, MVVM, Binding, DependencyObject
on Mon, Mar 29 2010 11:56 AM

In fact, there was a way to create data binding on properties of non-FrameworkElement objects in Silverlight 3. This is what the existing behaviors in Silverlight 3 do (such as the Silverlight 3 version of InvokeDataCommand, or my EventToCommand in the SL3 version of MVVM Light Toolkit. This involves a binding listener (which is a FrameworkElement) and some magic in the DependencyPropertyChanged event handler.

The situation in Silverlight 4 is much cleaner however, and I was able to get rid of a lot of hacky code in the SL4 version of EventToCommand, which makes me a happy camper (as I said at MIX, code is what crashes your application, so you want to minimize the amount in your application) ;)

Cheers,

Laurent

Laurent wrote re: Silverlight 4, Blend 4, MVVM, Binding, DependencyObject
on Mon, Mar 29 2010 11:58 AM

Side note: One of the reasons why I wrote EventToCommand and didn't just reuse the InvokeDataCommand is that you cannot bind the CommandParameter in SL3. I think it was an oversight of the Blend team, because you can actually bind the Command property, so using the exact same mechanism you can apply the same to CommandParameter. There were other reasons that made me write my own, but this one was a decisive one.

Cheers,

Laurent

Laurent wrote re: Silverlight 4, Blend 4, MVVM, Binding, DependencyObject
on Mon, Mar 29 2010 12:01 PM

@ Shaggygi : The InvokeCommandAction binds an event to an ICommand. The CallMethodAction binds an event to a method call. I prefer the Command one, because the other one involves some reflection (to find and execute the method), so there is a perf hit. Also, AFAIK there is no way to pass a parameter to the method, while the Command one can use the CommandParameter (1 param only but better than nothing). Finally, having commands exposed on a ViewModel is a well known way to invoke methods on an object in WPF and SL. I would love to be able to bind events to methods, but I think this should be a feature of the framework itself.

Cheers,

Laurent

uberVU - social comments wrote Social comments and analytics for this post
on Fri, Apr 2 2010 4:47 AM

This post was mentioned on Twitter by jrguay: Silverlight 4, Blend 4, MVVM, Binding, DependencyObject: I was thinking about an aspect of the new MV... http://bit.ly/9Spdkb (by @mtaulty)

Satish wrote re: Silverlight 4, Blend 4, MVVM, Binding, DependencyObject
on Fri, Apr 9 2010 8:07 AM

Iam looking for a callout or a balloon tooltip in my application. I found this callout shape in Expression Blend to suit the requirements. Pls let me know, if this callout control could be used in VS2008 as well. If not, pls suggest a way to create callout control.

Thanks,

Satish