I’m trying to fetch some of my UI content (text from textboxes) as parameters into my ICommand method, located in my ViewModel.
First of all, I got this RelayCommand implementation:
/// <summary>
/// A command whose sole purpose is to relay its functionality to other
/// objects by invoking delegates. The default return value for the
/// CanExecute method is 'true'.
/// </summary>
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
/// <summary>
/// Creates a new command that can always execute.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameters)
{
return _canExecute == null ? true : _canExecute(parameters);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameters)
{
_execute(parameters);
}
#endregion // ICommand Members
}
I declared a command in my ViewModel like this:
public ICommand AddEntityCommand
{
get
{
if(_addEntity == null)
{
_addEntity = new RelayCommand(AddEntityToDb);
}
return _addEntity;
}
}
That’s my xaml definition:
<Label Content="Entity Name:" Name="label1"/>
<TextBox Name="textBox_EntityName" />
<Label Content="Entity Type:" Name="label2" />
<TextBox Name="textBox_EntityType" />
<Button Content="Add" Name="btnAdd" Command="{Binding Path=AddEntityCommand}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource MultiParamConverter}">
<Binding Path="Text" ElementName="textBox_EntityName" />
<Binding Path="Text" ElementName="textBox_EntityType" />
</MultiBinding>
</Button.CommandParameter>
</Button>
and finally that’s my Converter:
public class MultiParamConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (object)values;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
I debugged the tool several times, and the debugger stops within the converter as soon as I changed a value in a text box. In this case, the values from the UI are shown within the
object[] values
parameter.
Clicking the Button, wouldn’t let me stop within the convert but it calls the method
AddEntityToDb
correctly, but the parameter, which has the type object[], contains always two elements which are both null.
I think I did something terribly wrong creating the AddEntityCommand, but I can’t figure it out on my own.
But what is the reason that the parameter of AddEntityToDb contains always two null elements?
I don’t know why it isn’t working as expected, but anyway you don’t really need to use command parameters… You could bind the textboxes to properties of your ViewModel, and use the values of these properties in your
AddEntityToDbmethod. This is the most common way to do it in MVVM…EDIT: I reproduced your initial problem with the converter. I think the reason is that the
MultiBindingclears thevaluesarray after the call toConvert(probably to avoid memory leaks). The fix is to clone the array instead of returning directly: