How can I pass two command parameters using a WPF binding?

c00012 716 Reputation points
2021-02-18T08:32:06.153+00:00

I'm writing code for wpf app using MVVM which has following UI;

69383-ice-screenshot-20210218-172152.png

when I enter name and age of someone in the app, message box will say:
"Happy Birthday, {Name}!, Age: {Age}"

Following is code for the app:
<Command>

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;

namespace WpfApp2.ViewModel
{
public class MyCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private Action<string,string> _execute;

    public MyCommand(Action<string,string> execute)  
    {  
        _execute = execute;  
    }  

    public bool CanExecute(object parameter)  
    {  
        return true;  
    }  

    public void Execute(object parameter)  
    {  
        var values = (object[])parameter;  
        _execute.Invoke(values[0] as string ,values[1] as string);  
    }  
}  

}

<ViewModel>

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;

namespace WpfApp2.ViewModel
{
public class MyViewModel
{
//public string nameText { get; set; }
//public string ageText { get; set; }

    public MyCommand DisplayBirthdayCommand { get; private set; }  

    public MyViewModel()  
    {  
        DisplayBirthdayCommand = new MyCommand(DisplayBirthday);  
    }  

    private void DisplayBirthday(string nameText, string ageText)  
    {  
        MessageBox.Show(string.Format("Happy Birthday, {0}!  Age: {1}", nameText,Convert.ToInt32(ageText)+1), $"{nameText}'s Birthday");  
    }  
}  

}

To pass multiple command parameter to Command, I made converter:
<converter>

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows.Data;

namespace WpfApp2.ViewModel
{
public class TextBox
{
public string FirstBoxValue { get; set; }
public string SecondBoxValue { get; set; }
}

public class MyConverter : IMultiValueConverter  
{  
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)  
    {  
        return new TextBox()  
        {  
            FirstBoxValue = values[0].ToString(),  
            SecondBoxValue = values[1].ToString()  
        };  
    }  

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)  
    {  
        throw new NotImplementedException();  
    }  
}  

}

I didn't get any error till I run app. when I run the app, I got following error:
69380-ice-screenshot-20210218-171926.png

I couldn't figure what's wrong with this code. How can I fix this?
if someone give me an advice, I'd be very appreciated.

thanks,
seihyung

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,696 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,306 Reputation points
    2021-02-18T15:12:31.337+00:00

    Hi,
    you can use CommandParameter binded to DataContext (=MyViewModel). Try following demo with yours code:

    XAML MainWindow:

    <Window x:Class="WpfApp2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp2"
            xmlns:vm="clr-namespace:WpfApp2.ViewModel"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="211">
      <Window.DataContext>
        <vm:MyViewModel/>
      </Window.DataContext>
      <Window.Resources>
        <Style TargetType="Label">
          <Setter Property="Margin" Value="5"/>
        </Style>
        <Style TargetType="TextBox">
          <Setter Property="Margin" Value="5"/>
        </Style>
        <Style TargetType="Button">
          <Setter Property="Margin" Value="5"/>
        </Style>
      </Window.Resources>
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="Auto"/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Label Grid.Row="0" Grid.Column="0" Content="Name:"/>
        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding nameText}"/>
        <Label Grid.Row="1" Grid.Column="0" Content="Age:"/>
        <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ageText}"/>
        <Button Grid.Row="2" Grid.Column="1" Content="Birthday" 
                Command="{Binding DisplayBirthdayCommand}" CommandParameter="{Binding}"/>
      </Grid>
    </Window>
    

    MyCommand:

    using System;
    using System.Windows.Input;
    
    namespace WpfApp2.ViewModel
    {
      public class MyCommand : ICommand
      {
        public event EventHandler CanExecuteChanged;
        private Action<object> _execute;
        public MyCommand(Action<object> execute) => _execute = execute;
        public bool CanExecute(object parameter) => true;
        public void Execute(object parameter) => _execute.Invoke(parameter);
      }
    }
    

    MyViewModel:

    using System;
    using System.Windows;
    
    namespace WpfApp2.ViewModel
    {
      public class MyViewModel
      {
        public string nameText { get; set; }
        public string ageText { get; set; }
        public MyCommand DisplayBirthdayCommand { get; private set; }
        public MyViewModel()
        {
          DisplayBirthdayCommand = new MyCommand(DisplayBirthday);
        }
        private void DisplayBirthday(object state)
        {
          MyViewModel vm = state as MyViewModel;
          MessageBox.Show(string.Format("Happy Birthday, {0}!  Age: {1}", vm.nameText, Convert.ToInt32(vm.ageText) + 1), $"{vm.nameText}'s Birthday");
        }
      }
    }
    
    0 comments No comments