You are on page 1of 3

Passing two command parameters using a WPF binding.

I have a command which I am executing from my XAML file using the following standard syntax:
<Button Content="Zoom" Command="{Binding MyViewModel.ZoomCommand}"/>

This worked fine until I realized that I needed TWO pieces of information from the view in order to make this operation complete the way users expect (the width and height of the canvas specfically). It seems like it's possible to pass an array as an argument to my command, but I don't see there being a way to specify the binding to my two canvas properties in the CommandParameter:
<Button Content="Zoom" Command="{Binding MyViewModel.ZoomCommand" CommandParameter={Binding ElementName=MyCanvas, Path=Width}"/>

up vote 10 down vote favorite 8

How do I pass both Width and Height to my command? It doesn't seem like this is possible using commands from XAML and I need to wire up a click handler in my codebehind to get this information to pass to my zoom method. wpf binding path command asked Aug 29 '09 at 5:58 link|improve this question JasonD 3712311 Was this post useful to you?

2 Answers
active oldest votes Firstly, if you're doing MVVM you would typically have this information available up vote 20 to your VM via separate properties bound from the view. That saves you having to down vote pass any parameters at all to your commands. accepted

However, you could also multi-bind and use a converter to create the parameters:
<Button Content="Zoom" Command="{Binding MyViewModel.ZoomCommand" CommandParameter={Binding ElementName=MyCanvas, Path=Width}" <Button.CommandParameter> <MultiBinding Converter="{StaticResource YourConverter}"> <Binding Path="Width" ElementName="MyCanvas"/> <Binding Path="Height" ElementName="MyCanvas"/> </MultiBinding> </Button.CommandParameter> </Button>

In your converter:
public class YourConverter : IMultiValueConverter { public object Convert(object[] values, ...) { return values; } ... }

Then, in your command execution logic:


public void OnExecute(object parameter) { var values = (object[])parameter; var width = (double)values[0]; var height = (double)values[1]; }

HTH, Kent answered Aug 29 '09 at 9:50 link|improve this answer Kent Boogaart 49k468110 Thanks Kent - that was exactly what I was looking for. I like your first approach better so that the VM knows the "state" of the view through a binding without me having to pass parameters at all, but I can still test it. I'm not sure that's going to work for me here, as I need the view to make the canvas as big as possible and pass this value to the VM. If I bind it, won't I have to set the width in the VM? In which case, the VM is bound to the view? JasonD Aug 29 '09 at 18:32 @Jason: you can do it either way. That is, have the view push changes back to the view model, or have the view model push changes to the view. A TwoWay binding will result in either option being available to you. Kent Boogaart Aug 29 '09 at 19:08

Thanks Kent, I actually got it working exactly like that. Super helpful - thanks so much! JasonD Aug 30 '09 at 21:28 feedback

Use Tuple in Converter, and in OnExecute, cast the parameter object back to Tuple. public class YourConverter : IMultiValueConverter { public object Convert(object[] values, ...) { Tuple< string, string > tuple = new Tuple< string, string >((string)values[0], (string)values[1]); return (object)tuple; } } public void OnExecute(object parameter) { var param= (Tuple< string, string >) parameter; }

up vote 2 down vote

You might also like