2

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?

0

2 Answers 2

3

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 AddEntityToDb method. 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 MultiBinding clears the values array after the call to Convert (probably to avoid memory leaks). The fix is to clone the array instead of returning directly:

using System.Linq; ... public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return values.ToArray(); } 
Sign up to request clarification or add additional context in comments.

7 Comments

actually? Hm, ok, I did not thought about doing it this way so far, because I was trying to figure out how to use CommandParameters instead. But anyway, thanks for your contribution, this will solve my problem. According to your answer there is nothing I did basically wrong ?
I'm getting crazy - I set up the Binding to my ViewModel's locals, but I'm setting the textboxes programatically via textBox.Text = "anyText" but the Binding (TwoWay Mode) does not recognize that :(
Why are you setting the textboxes programmatically? Just set the bound properties in the ViewModel...
Got it working using "UpdateSourceTrigger=PropertyChanged" - no as i mentioned i wanted to get values from the UI into my ViewModel. On default, I guess the binding only recognizes new data if the textbox looses the focus.
Looks like your problem is that you're trying to bind to your TextBoxes when your DataContext is your viewModel = the TextBoxes are not found by the binding. Follow what Thomas suggested as getting values straight from the TextBoxes is basically a pattern-breaker and shouldn't be done. Everything should bind into the ViewModel.
|
0

UPDATE: try this

public class MultiParamConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return new Tuple<string, string>((string)values[0], (string)values[1]);; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } 

viewmodel

public void AddEntityToDb(object parameter) { var values = (Tuple<string, string>)parameter; var text1 = values.Item1; var text2 = values.Item2; } 

8 Comments

I think you misunderstood the question... the OP's problem is that values[0] and values[1] are null.
hmm he wrote: "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" so the problem is that he try to return (object)values, instead of values
How can casting object[] to object introduce any problem?
I guess it is not the casting, causing a problem, but anyway, the suggested solution is not working too.
sorry i copied the wrong example. updated and tested successfully ;)
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.