Using RelayCommands in Silverlight 3 and WPF

Like most of us have found out the hard way, Silverlight 3 and Windows Presentation Foundation 3.5 are two quite similar beasts, but not totally the same. Silverlight is often presented as a subset of WPF (in fact, some features are available in Silverlight but not yet in WPF; generally speaking, though, it is true that Silverlight has less features than its big sister WPF) (yeah WPF is a girl, don’t tell me you didn’t know ;))

No Commands in Silverlight 3

One of the missing parts is Commanding. Commands in WPF are used as a kind of “weak events”, i.e. they can be used to execute an action when a control is actuated (just like an event), but without the tight coupling that an event brings with it. You can specify a Command on an object, and bind this command to a control in a completely different part of your application. You can have one person write the Command (typically a developer), and a completely other person (typically a designer) use the Command in the user interface. More interestingly, the designer can change the look and feel, for example replacing a series of Buttons by a Menu and MenuItems, and the developer doesn’t need to change anything to the code.

In Silverlight, parts of the “plumbing” are available already (the ICommand interface) but most of it is missing. This led some very clever people to implement Commands in Silverlight, to replace the missing pieces by a custom implementation. In Prism, the command implementation is called DelegateCommand. In my MVVM Light Toolkit, I use a command that my good friend, colleague at IdentityMine and fellow WPF Disciple Josh Smith created, called the RelayCommand.

Now, the beautiful part is that RelayCommands (and DelegateCommands too) work wonders in Silverlight, but also in WPF. RelayCommands are making your life much easier in WPF too. No need to implement complicated code to bind the control to your method, just use a RelayCommand to do that. And since the implementation is (almost) the same in Silverlight too, you can share code between Silverlight and WPF.

The Execute Method

When the control to which a Command is bound is actuated by the user, the Execute method is called. This method is specified by the ICommand interface, and every ICommand implementation must offer it (and of course RelayCommand does).

The Execute method is passed to the RelayCommand’s constructor in form of an Action (or Action<T> if the command has a parameter, in which case you must use the RelayCommand<T> class).

Note: An Action is a method  (returning void) that can be passed to another object, for example as a parameter. It is something like a method pointer. If the method that the Action represents has a parameter, you must use Action<T> where T is the parameter’s type. There are also additional Action implementations with more than one parameters, but RelayCommand can only have 0 or 1 parameter.

The code to create a RelayCommand is:

public RelayCommand MyCommand
{
    get;
    private set;
}

public MainViewModel()
{
    MyCommand = new RelayCommand(
        () => DoSomething());
}

Note: The syntax () => DoSomething() is called a lambda expression, and is the shortest way to define and pass an Action to an object. In the sample here, the method DoSomething will be called without any parameter when the Command is executed.

CanExecute and CanExecuteChanged

Apart from the Execute method that the ICommand interface specifies, there is an additional method and an event that every ICommand (including, of course, RelayCommand) must offer.

  • CanExecute: This method should return true if the command can be executed. When the Command is used on a control, the control will be disabled automatically when CanExecute returns false.
  • CanExecuteChanged: This event should be raised when the CanExecute method must be “requeried” (when the value of CanExecute might have changed, and should be re-evaluated).

The CanExecute method can be passed to the RelayCommand constructor as a Func<bool> (or a Func<T, bool> if the command has a parameter).

Note: A Func is exactly like an Action, except that it has a return type. In the case of RelayCommands, the return type is bool: True if the command can be executed, false otherwise.

To create a command with an Execute and a CanExecute methods, you can do:

public RelayCommand MyCommand
{
    get;
    private set;
}

public MainViewModel()
{
    MyCommand = new RelayCommand(
        () => DoSomething(),
        () => return MyValue);
}

In the code above, if MyValue is true, the command can be executed; if it is false, the command cannot be executed (and controls using that command are disabled). This can depend on multiple parameters such as the state of the application, the time of the day, the weather outside, etc.

Note: When using lambda expressions, if the expression is just “return something”, the “return” keyword can be omitted. So the code becomes:

public RelayCommand MyCommand
{
    get;
    private set;
}

public MainViewModel()
{
    MyCommand = new RelayCommand(
        () => DoSomething(),
        () => MyValue);
}

The CommandManager

RelayCommands are available for WPF and Silverlight. However, one piece is missing in Silverlight: Windows Presentation Foundation has a class that is watching your UI, and that polls the commands’ state when something happens (for example when the user clicks a button, checks a checkbox, open a menu, etc…). This class is called the CommandManager and it doesn’t exist in Silverlight. Not at all. Nada.

So when a user actions the UI in WPF, this triggers the CommandManager to requery all the commands. In Silverlight you have to do the work yourself. This is why the RelayCommand class has a method called RaiseCanExecuteChanged. This method forces the control that uses the command to check again if the command may be executed or not. And if the command may not be executed, the control is disabled.

In WPF

Strictly speaking, in WPF, and if your command is bound to a control that is watched by the CommandManager, you shouldn’t have to raise the CanExecuteChanged event yourself. You can let the CommandManager handle the situation. That said, external events might also change the state of the UI. Let’s imagine that the UI should be enabled from 9AM to 5PM, and then disabled for the night. The user is not triggering the UI, so the code should request (politely) that the CommandManager requeries the state of the commands. This is done by calling the method InvalidateRequerySuggested on the CommandManager. And as you guessed, the method RaiseCanExecuteChanged of the RelayCommand class does just that.

And in Silverlight

However, since Silverlight doesn’t have the CommandManager, a little more manual work is involved. When the state of your object changes in a way that affects the UI, you must RaiseCanExecuteChanged on the corresponding commands. In Silverlight, this will raise the CanExecuteChanged event, thus forcing the bound controls to call CanExecute. In WPF,  like we just saw, this will call InvalidateRequerySuggested on the CommandManager.

Show me the code

I created a small demo to illustrate this in Silverlight and in WPF, using the MVVM Light Toolkit. Most of the code is shared between WPF and Silverlight. The source code for the application is available as usual (WPF 3.5 SP1 and Silverlight 3).

The demo exposes one command, created in the MainViewModel class:

public RelayCommand IncreaseCounterCommand
{
    get;
    private set;
}

public MainViewModel()
{
    IncreaseCounterCommand = new RelayCommand(
        () => Counter++,
        () => CanIncrement);
}

The Counter and CanIncrement properties are raising the PropertyChanged event when they are modified, thus data bindings that refer to these two properties will be updated whenever the properties are modified. What the code above means is: When the IncreaseCounterCommand is executed, check the CanIncrement property. If it is true, increment the Counter property.

2009092601

Figure 1: WPF demo application, Enabled and Disabled

Disabling the button

We have a manual way to enable/disable the “increment” button: If you click on the “Enabled” text, it will turn into “Disabled”. This text (it’s a ToggleButton) is bound to the CanIncrement property directly. So in fact, when the text is “Disabled”, the CanIncrement property is set to false.

Of course, we want the controls using this command to be automatically disabled/enabled when the CanIncrement property changed. In WPF, nothing needs to be done, because the CommandManager will automatically requery the state of the commands when the user clicks on the UI. In fact the state of the commands is requeried very, very often during the course of the application. Even just moving the mouse on the UI causes the CommandManager to requery the state of commands bound to visible UI element.

In Silverlight however, no CommandManager, so we need to raise the CanExecuteChanged event on the command manually. Note that raising the CanExecuteChanged event can be useful in WPF too if you change the CanIncrement property in the code, for example through a timer. So, in fact, we will just call IncreaseCounterCommand.RaiseCanExecuteChanged() in Silverlight and in WPF too when CanIncrement changes:

public bool CanIncrement
{
    get
    {
        return _canIncrement;
    }

    set
    {
        if (_canIncrement == value)
        {
            return;
        }

        _canIncrement = value;

        // Update bindings, no broadcast
        RaisePropertyChanged(CanIncrementPropertyName);

        IncreaseCounterCommand.RaiseCanExecuteChanged();
    }
}

Just a warning: In V1 of the MVVM Light Toolkit, the method RaiseCanExecuteChanged was taking a boolean parameter. This boolean was actually not very useful, and has been removed in V2. Calling the old method still works in V2, but the parameter has no effect, and the method has been marked Obsolete. It will be removed in a future version of the toolkit.

This sample uses V2 beta of the MVVM Light Toolkit.

Silverlight/WPF Compatibility

Much of the code is shared between Silverlight and WPF in this small demo.

  • The ViewModel code is completely shared. The source code files are physically into the WPF project, and added as links into the Silverlight project. Implement once, compile twice.
    To add a source code file as a link, choose “Add existing item” in Visual Studio. Then, select a file. Instead of clicking on Add, click on the arrow on the right of the Add button, and select “Add as a link”.
  • The resources defining the look&feel of the application are placed into the file Skins\MainSkin.xaml. The code n this file is 100% the same in WPF and in Silverlight. To reuse the Silverlight control templates in WPF too, I use the WPF Toolkit’s implementation of the Visual State Manager.
  • Finally, the XAML code in the main UI element (MainWindow.xaml in WPF, and Page.xaml in Silverlight) is almost the same, except for one little difference: Since Silverlight doesn’t support commands out of the box, we rely on an attached behaviour to bind the RelayCommand to the Button:
<Button cmd:ButtonBaseExtensions.Command="{Binding IncreaseCounterCommand}"
        Grid.Row="2"
        Style="{StaticResource IncrementButtonStyle}"
        Content="Increment" />

Conclusion

Commands in WPF are quite a complex topic, and I must admit that I didn’t completely understand them before I discovered the RelayCommand class. I totally fell in love with this fantastic helper. Josh Smith has been fantastic in allowing me to re-use his code in the MVVM Light Toolkit. I hope that this article will help you understand the power and convenience of RelayCommands. Happy coding!

 

Print | posted on Saturday, September 26, 2009 7:15 AM

Feedback

# re: Using RelayCommands in Silverlight and WPF

left by Josh at 9/26/2009 8:33 PM Gravatar
This feature is already implemented in Prism/CAG almost identically:

http://prism.codeplex.com/

In V2 which released in February. It also contains a DelegateCommand which is similar to RelayCommand but based on John Gossman's original from Blend.

# re: Using RelayCommands in Silverlight and WPF

left by Laurent Bugnion at 9/26/2009 10:00 PM Gravatar
Hi Josh,

You are right, and this is not the only thing that is similar to what Prism is offering. As I mentioned on your own blog, I also have a Messenger which is an implementation of the Event Aggregator.

The goal of the toolkit is to offer an alternative, directly targeted at MVVM (while Prism is targeted at composite applications, with some of the elements that can be used for MVVM), and in a form that works best with Expression Blend. This is a lighter framework than Prism, which should be easier to start with, and which integrates better in Blend for the design time experience.

Glenn Block and I argued a LOT about reusing pieces of Prism, packaging them differently, or implementing something slightly different. I chose the second approach mostly because this gives me more flexibility in pushing changes that the community requests. This is already what happened with the Messenger V2 (I will post the beta later today), and I expect the same to happen to other pieces too). I think that Glenn (who was an alpha tester) agrees with me that the toolkit is a very light and flexible approach to MVVM, and easy to integrate in existing applications (including those built with IoC etc...).

Thanks for your feedback, and don't hesitate to give more if you have suggestions.

Cheers,
Laurent

# re: Using RelayCommands in Silverlight and WPF

left by Raghuraman at 10/4/2009 11:02 AM Gravatar
Great Work Guys !!!

This will pull down the learning curve for wannabe MVVM implementations in SL.

Keep it up.

# re: Using RelayCommands in Silverlight and WPF

left by ETFairfax at 10/19/2009 8:20 PM Gravatar
Hi,

I'm brand new to all of this Silverlight/MVVM stuff, so please be gentle!!

If I have a user control which hass two buttons and include that on my page. Is it possible to add a command to the Click event of each of the two buttons? Something like....

<uc:MyUserControl SaveEvent="{Binding Path=SaveCommand}" CancelEvent="{Binding Path=CancelCommand}" />

I've got commands working with single buttons i.e...

<Button Content="Delete" cmd:ButtonBaseExtensions.Command="{Binding Path=DeleteCommand}" />

But can't work out what i need to do to make this work on a user control.

Does that make sense??

Cheers,

ETFairfax.

# re: Using RelayCommands in Silverlight and WPF

left by Laurent at 10/19/2009 9:50 PM Gravatar
Hi,

It does make a lot of sense. Historically, this restriction comes from WPF, where only some controls (all ButtonBase, MenuItems...) implement ICommandSource, which specify the Command property. Only these controls can have a Command, and the command is only activated on Click event.

Thankfully, there are ways around that, and I am working on a new version of the MVVM Light toolkit that will include a "Event to Command" binder. It will be strongly inspired from works by the Expression Blend team as well as Orktane's nRoute toolkit, so in the mean time I encourage you to check these.

If you prefer to stick with the MVVM Light toolkit, one transient measure you can take is to handle the event in the code behind, and execute the command from there. This way, when the EventToCommand binder is available, you can just remove the code behind and do that in the XAML instead.

http://expressionblend.codeplex.com/

http://www.orktane.com/Blog/post/2009/10/10/Introducing-nRouteToolkit-for-Silverlight-(Part-II).aspx

Cheers,
Laurent

# re: Using RelayCommands in Silverlight and WPF

left by ETFairfax at 10/20/2009 9:15 PM Gravatar
Nice one Laurent. I'll have a look at those resources.

I look forward to the next release of the toolkit.

Thanks,
ETFairfax

# re: Using RelayCommands in Silverlight 3 and WPF

left by Werner at 1/19/2010 11:12 PM Gravatar
Hi!

Any news on that EventToCommand binder?

Really really would like that. PRISM's way of getting custom events to work is way way way to involved for my taste.

;)

# re: Using RelayCommands in Silverlight 3 and WPF

left by Laurent at 1/19/2010 11:40 PM Gravatar
Hey Werner,

Yes, EventToCommand is available in the latest release of the toolkit. See
http://blog.galasoft.ch/archive/2009/11/13/bug-correction-in-messenger-and-new-feature-in-eventtocommand-mvvm.aspx

and also

http://blog.galasoft.ch/archive/2009/12/17/silverlight-4-dragampdrop-with-eventtocommand.aspx

Hope this helps!
Laurent

# re: Using RelayCommands in Silverlight 3 and WPF

left by Werner at 1/20/2010 12:22 AM Gravatar
That is excellent news. I have found those extentions hiding in "extras".

I have another question. For some bizarre reason I cannot find the ButtonBaseExtensions part of the Commanding inside your MVVM.Lite library.

What am I misssing? If I do a keyword search throughout MVVM.Lite I find now references to that name. I am under the understanding that it must come from MVVM.Lite?

What am I not getting here?

# re: Using RelayCommands in Silverlight 3 and WPF

left by Laurent at 1/20/2010 12:40 AM Gravatar
Hi,

ButtonBaseExtension is only needed (and available) in the Silverlight 3 version of the toolkit. In the WPF 3.5, WPF 4 and Silverligh 4 versions, you should use the built-in property Command which is available on all ButtonBase instances.

In the Silverlight 3 version, this class is available in the GalaSoft.Mvvm.Command namespace.

Make sure that you have the correct version of the DLLs if you need this class!

Cheers,
Laurent

# re: Using RelayCommands in Silverlight 3 and WPF

left by Werner at 1/20/2010 12:46 AM Gravatar
Aah!

I did not know this.

I am indeed working with SL4. I was aware that SL4 has some commanding support, but also just on buttons. It's your EventToCommand binder I was aftet so I did not check was already available in SL4

The commanding is working now.

Thanks allot!

Werner

PS - Awesome toolkit I like it

# re: Using RelayCommands in Silverlight 3 and WPF

left by Dave at 2/25/2010 4:55 AM Gravatar
Great article! I am planning on using your toolkit, but am currently looking into problems where my GUI doesn't actually update as expected; when properties that govern whether my command CanExecute or not change, the GUI doesn't update unless I actually click. Just moving the mouse isn't enough. I am thinking about calling InvalidateRequerySuggested in a Timer for now, until I can implement your toolkit. What are your thoughts on that? Oh, and I'm using WPF with .NET 3.5 SP1

# re: Using RelayCommands in Silverlight 3 and WPF

left by Arun at 8/27/2010 7:59 PM Gravatar
Hi,
I want to add Controls dynamically from ViewModel. I have to add Button and Textbox dynamically to the Grid. In the ViewModel constructor call I need to add the controls. I am not getting how to get the Grid control reference in my ViewModel. Can anybody help me on this?
Thanks in advance

# re: Using RelayCommands in Silverlight 3 and WPF

left by Andy at 8/30/2010 8:52 AM Gravatar
Hey Laurent,
I'm working on a MVVM Application using your toolkit. I am building a Silverlight and WPF version, and would like to reuse part as much as possible. I have everything working except the Views.

Say I have a MainView in my Silverlight application, which my WPF application has added as a link. I run into a problem trying to build because of the EventToCommand behavior namespace which uses the MvvmLight.Extras.SL4, where as the WPF uses the Extras.WPF equivalent. So, my WPF version throws an error on the MainView.

What is the best way to link XAML views between Silverlight & WPF using your toolkit (which is AWESOME by the way... MVVM rocks)?
Thanks

# re: Using RelayCommands in Silverlight 3 and WPF

left by Rick Ratayczak at 8/30/2010 10:56 AM Gravatar
Andy, it is better if you make the WPF app first, using Visual State Manager and not triggers, than it is easier to port to silverlight, versus the other way around.

# re: Using RelayCommands in Silverlight 3 and WPF

left by Andy at 8/31/2010 4:32 AM Gravatar
Rick,
Thanks for the reply. Won't I run into the same problems (with the Extras.WPF vs SL)?

Currently, I fixed the issue by just using built in button commands for silverlight, and modifying the application so my EventToCommand controls could be cut out. I was then running into toolkit issues (DatePicker and Wrap Panel, in particular) where they are built into WPF, but in the Silverlight toolkit. Thus, the toolkit namespace did not apply to WPF version.

Does it really make it that much easier to share views, as I am trying to do, when you do WPF first? I just thought doing SL first would be easier because "everything" in SL you can do in WPF, but not the other way around.

# re: Using RelayCommands in Silverlight 3 and WPF

left by Sung Kim at 9/5/2010 3:41 PM Gravatar
> “Add as a link”
What is the advantage of using “Add as a link” instead of creating a common library?
Saving lines?

# re: Using RelayCommands in Silverlight 3 and WPF

left by Laurent at 9/6/2010 12:18 AM Gravatar
There is an issue of binary compatibilty that adding as Link solves. Silverlight 3 is not binary compatible (well, almost not) with WPF. Silverlight 4 is better, but not quite there yet. As for WP7, it's even worse. By using Add as link, you don't have this issue at all.

Makes sense?
Laurent

# re: Using RelayCommands in Silverlight 3 and WPF

left by roberto at 9/14/2010 1:08 AM Gravatar
Hello Laurent, i'm using your toolkit to build my first application in sl4, i'have a problem when i navigate from a view to another:
I call base.CleanUp, but (and i see this with winDBG) the view and the viewmodel still stay in memory.

Could be a related problem to some link beetween viewmodel and view caused by relayCommand?

# re: Using RelayCommands in Silverlight 3 and WPF

left by Brijen at 9/15/2010 5:04 AM Gravatar
I am using your toolkit for WP7. What's the guideline to move from Page 1 to Page 2. I have button on page 1 and on click event want to move to page 2.

Could you please share the sample code or app...

# re: Using RelayCommands in Silverlight 3 and WPF

left by dan at 9/17/2010 1:12 AM Gravatar
I'm falling in love with this framework, but you really REALLY need to have more samples or documentation. As it is, it's mostly "just figure it out".

Specifically regarding this example, for it to be complete you should really show how you would impose a Counter limit and actually use CanIncrement.

Looking forward to figuring out more of this!

# re: Using RelayCommands in Silverlight 3 and WPF

left by dan at 9/17/2010 1:14 AM Gravatar
Also, I understand the interest in proving it possible, but what is the value of sharing 100% code between WPF and SL. You'd obviously have to program to the lowest common denominator (SL), so at that point why even bother with WPF? Or is it just an exercise to prove it's possible?

Does WPF not require an additional installation beyond the .Net framework? Is that the advantage of WPF over SL in this scenario (developing both)?

# re: Using RelayCommands in Silverlight 3 and WPF

left by andrew lindzon at 10/3/2010 4:40 AM Gravatar
I am just getting started with MVVM Light, and I am trying to figure out how to communicate a close request to the MainPage so it can close the current tab. The user will click on a button which will trigger a command in the CustomerView which will first deal with any data issues using the customerviewmodel, then it needs to tell the MainPage to terminate the view and close the current tab.

How would you do that?

# re: Using RelayCommands in Silverlight 3 and WPF

left by ursri at 10/27/2010 9:43 PM Gravatar
Hi,
Can dynamic method parameters set to relaycommand using method name and reflection techniques?

Thanks
ursri

# re: Using RelayCommands in Silverlight 3 and WPF

left by Michael Stone at 11/15/2010 11:37 PM Gravatar
I'm using the latest version of the toolkit and RelayCommand does not seem to have the RaiseCanExecuteChanged method. Has that been removed in the latest release? If so, what should I use instead?

Thanks

# re: Using RelayCommands in Silverlight 3 and WPF

left by Shawn Featherly at 3/4/2011 2:00 AM Gravatar
@dan, CanIncrement is used by the dis/enable button. Add a counter limit by adding a condition to the Counter property's set: block
else if (value == 10) CanIncrement = false;

After trying to make it decrement after hitting 10, I found changing the RelayCommand's Action execute after it was set didn't work as I wanted, neither by setting IncreaseCounterCommand to a new RelayCommand or by using IncreaseCounterCommand.Execute(new Action(() => Counter--)).

The working method I found was making the execute action not need to be changed, to more flexible. I used "Counter += step" instead of "Counter++". "step" being a private integer that was changed in the "else if (value == 10)".

# re: Using RelayCommands in Silverlight 3 and WPF

left by Vijay at 3/15/2011 6:05 AM Gravatar
I do not see reply to Andy's problem. Was just thinking if Attached Command Behavior would solve the problem. I am not sure if ACB is supported by SL or not, but works well with WPF.

# re: Using RelayCommands in Silverlight 3 and WPF

left by Allen Marshall at 3/21/2011 12:56 PM Gravatar

I do not seem to be able to use the version of RelayCommand<T> as shown below. I get the message "Cannot implicitly convert type ....RelayCommand<Theme> to ...RelayCommand
Is there some magic to passing an argument to a relay command or am I just clueless? Or worse, is the argument mandated to be a simple type?

/// <summary>
/// Switch the theme application wide
/// </summary>
public bool CanSwitchTheme
{
get
{ return true; }
}
private RelayCommand _switchThemeCommand;

public RelayCommand SwitchThemeCommand
{
get
{
if (_switchThemeCommand == null)
{
_switchThemeCommand = new RelayCommand<Theme>(( Theme param ) => LookAndFeelHelper.SwitchTheme(param),
(Theme param) => this.CanSwitchTheme);
}
return _switchThemeCommand;
}

}

# re: Using RelayCommands in Silverlight 3 and WPF

left by Allen Marshall at 4/12/2011 12:47 AM Gravatar
This question still remains.... any ideas?

# re: Using RelayCommands in Silverlight 3 and WPF

left by Laurent Bugnion at 4/18/2011 3:05 PM Gravatar
Hi,

Well RelayCommand<T> is not the same type than RelayCommand. If you want to use the code, you need to do

private RelayCommand<Theme> _switchThemeCommand;

Alternatively, this is also possible:

private ICommand _switchThemeCommand;

Cheers,
Laurent

# re: Using RelayCommands in Silverlight 3 and WPF

left by Allen Marshall at 4/19/2011 1:55 PM Gravatar
Yes, thank you. I must have mistyped, because the <T> approach was the desired one. I solved this by the following, and it works nicely, but is this ridiculous? Should I have been able to pass the Theme object as originally intended?

...
// SwitchThemeCommand - switch theme on theme selection
// takes a string argument containing an internal theme name from the Telerik Themes collection
SwitchThemeCommand = new RelayCommand<string>((t) => LookAndFeelHelper.SwitchTheme(t),
(t) => CanSwitchTheme);
...

# re: Using RelayCommands in Silverlight 3 and WPF

left by KennyWoo at 4/24/2011 11:05 AM Gravatar
I have just started to learn about MVVM Light .
It's strong and MVVM - oriented but i got a problem with it.
When i create a command CheckUser via RelayCommand on my ViewModel,i just found the RelayCommand<T> with only one parameter
I want something like CheckUser=new RelayCommand<string,string>((user,pass)=>....)
How can i do this with RelayCommand multi param or some method to resolve my problem.

# re: Using RelayCommands in Silverlight 3 and WPF

left by Laurent Bugnion at 4/25/2011 11:38 AM Gravatar
Hi,

The fact that there is only one parameter in commands is not due to MVVM Light, but to the ICommand interface, which is defined by Microsoft. The Execute method defined by this interface has only one parameter (which may be null).

Typically when you need more than one parameter, there are other ways to go around this limitation. For instance, data bind some properties of your ViewModel to some elements of your view. Then, when the command is executed, you can read the value of these properties to configure your method call.

HTH,
Laurent

# re: Using RelayCommands in Silverlight 3 and WPF

left by KennyWoo at 4/25/2011 1:43 PM Gravatar
Dear Laurent,

I still confuse about how do i resolve some method like as CheckLogin(string username,string pass) or InsertNewUser(string username,.....with multi param) from original WPF/Silverlight Project to MVVM pattern.
Can you give me some solution or sample to resolve my problem .
I developed WPF/Silverlight with no pattern before and now i've just moved to MVVM in few days.
I choose MVVM Light among so may MVVM framework like as Prism,Catel,Cinch,...
So you can give me some document about MVVM Light ?
Thanks & regard.

# re: Using RelayCommands in Silverlight 3 and WPF

left by Milind Chavan at 5/26/2011 10:45 AM Gravatar
Hi Laurent,
I am using MVVM light for the WPF application. The application uses the EventToCommand to bind the Icommand to Realycommand.

public ICommand Image_MouseLeftButtonUp
{
get { return _Image_MouseLeftButtonUp ?? (_Image_MouseLeftButtonUp = new RelayCommand((param) => this.Image_OnMouseLeftButtonUp())); }
private set { _Image_MouseLeftButtonUp = null; }
}

But I would like to know, how to deregister/unhook the binding with RelayCommand ?

Regards,
Milind.

# re: Using RelayCommands in Silverlight 3 and WPF

left by kamlendra at 6/24/2011 11:00 AM Gravatar
i am able to bind event to Icommand directly in XAML just one doubt.
how can i pass the argument like (object sender,EventArgs args)
w'll it be using commandparameter if yes please tell me the way.

# re: Using RelayCommands in Silverlight 3 and WPF

left by Laurent Bugnion at 6/28/2011 11:15 AM Gravatar
Hi,

You can pass only one parameter to an ICommand implementation. Use the CommandParameter property for this.

Cheers,
Laurent

# re: Using RelayCommands in Silverlight 3 and WPF

left by Andrew Strickland at 7/29/2011 8:28 PM Gravatar
Hi Laurent, I'm new to MVVM but I love it. Your toolkit has been a huge help, and your code and videos is quite clear.

I have a ComboBox in my XAML that is using the RelayCommand with EventToCommand that is fired when the ComboBox's SelectionChanged event is triggered.

My ViewModel has this handler:

HandleSuffixChangedComamnd = new RelayCommand<SelectionChangedEventArgs>(e =>
{
if(IsOtherSuffixSelected(e.AddedItems[0].ToString()))
{

}
});

The IsOtherSuffixSelected method checks the value of the selected item so see it it matches a value of "__Other__". What I want to do now is make a TextBox in the XAML display conditionally dependant on whether that returns true. What is the best way to do this while following the MVVM pattern? After all, the ViewModel shouldn't know anything about the View.

I assume I'm supposed to fire a manual property changed of some kind, and the TextBox would bind to that property somehow in it's "Visibility" property?

# re: Using RelayCommands in Silverlight 3 and WPF

left by Laurent at 7/29/2011 9:07 PM Gravatar
Hi,

When we say that the VM should not know the view, we mean that it shouldn't have a dependency on the view, because this complicates testing and maintainability (amongst other things). However, I see the VM as a kind of musical conductor for the orchestra that is the view. If you want to show/hide elements based on things happening in the VM, it is OK to have a corresponding property in the VM. For instance, imagine that you want to hide the login panel when the user is logged in. You can have two properties IsLoggedIn and LoginPanelVisibility. When IsLoggedIn changes (in the setter), you can RaisePropertyChanged for LoginPanelVisibilityPropertyName. The LoginPanelVisibility property only has a getter and returns Visible when IsLoggedIn is false, and vice versa.

This way you can easily add dependent properties in your VM. Having a property of type "Visibility" is OK, because you can easily unit test that this property changes depending on the status of IsLoggedIn..

Does it make sense?

Cheers,
Laurent

# re: Using RelayCommands in Silverlight 3 and WPF

left by Andrew Strickland at 7/29/2011 10:18 PM Gravatar
It does. I added the property:

/// <summary>
/// Gets the DisplayOtherSuffixText property.
/// </summary>
public bool DisplayOtherSuffixText
{
get
{
return _blnDisplayOtherSuffix;
}

set
{
if (_blnDisplayOtherSuffix == value)
{
return;
}

_blnDisplayOtherSuffix = value;

// Update bindings, no broadcast
RaisePropertyChanged(DisplayOtherSuffixTextPropertyName);
}
}

And set the value of that property in the RelayCommand Handler:

HandleSuffixChangedComamnd = new RelayCommand<SelectionChangedEventArgs>(e =>
{
if(IsOtherSuffixSelected(e.AddedItems[0].ToString()))
{
DisplayOtherSuffixText = true;
}
});

Then bound to that property in the XAML:

<TextBox x:Name="SuffixOtherText" Text="{Binding IdentifyingInformation.FullName.LegalName.Suffix_Other, Mode=TwoWay}" Grid.Column="2" Grid.Row="3" Visibility="{Binding DisplayOtherSuffixText, Converter={StaticResource BoolToVisibilityConverter}}" />

Oh, and created a simple converter that converts the bool from the property into a Visibility enum value. I guess I could have built that into the property itself but, this way I can re-use the converter elsewhere. Everything works now and it's all MVVM, no dependencies!

Thanks!

# Propertychange event and RelayCommand

left by EmanueleC70 at 10/25/2011 6:13 PM Gravatar
Hi, I have an issue i don't understand and resolve.
I have a datagrid and a button not directly linked to submitchange logic. I change a value in datagrid and without exit focus from that field i click the button.
I see the propery change event of my viewmodel called for the field change and HasChanges event of model, but it forget that i have clicked, so relaycommand does'nt fire. Thanks!

# re: Using RelayCommands in Silverlight 3 and WPF

left by Guido Smeets at 11/2/2011 2:27 PM Gravatar
I've noticed in WPF that at times the value of CanExecute and the enabledness of the button are out of sync. Whenever I interface with any UI element, it updates properly. This problem seems to mainly occur just after the user control has been loaded. I've fixed it with a manual call to InvalidateRequerySuggested for now, but this seems like an issue. Reading the other comments this seems to be the same problem that Dave brought up, any insights as to why this problem occurs?

# Mvvm Light Toolkit tutorial

left by Mojammel at 1/15/2013 12:16 PM Gravatar
Can anybody provide synchronized step by step tutorial for learning mvvm light toolkit?

I am very new in mvvm and want to learn about mvvm light but don't find any useful and synchronized tutorial for learning the toolkit.

Although some articles are available in net but what I saw that they aren't synchronized.

If anybody refer me any link for learning mvvm light a-z by an organized way please refer me or send me the documentation via mail. My mail address is mojampcds007@hotmail.com
Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: