Mahsa
Mahsa

Reputation: 507

Pass command parameter to method in ViewModel in WPF?

I am trying to pass CommandParameter to the method in my ViewModel. How to do this?

private void Open(object sender)
{
    if (sender==this.objMainWindow.btnHistory)
    {
        objMainWindow.Container.Child = objHistory;
    }

    if (sender == this.objMainWindow.btnNew_Item)
    {
        objMainWindow.Container.Child = objNewItem;
    }

    if (sender == this.objMainWindow.btnSide_Effects)
    {
        objMainWindow.Container.Child = objSideEffect;
    }
}

This is my meyhod in ViewModel that I want to pass CommandParameter. I use CommandParameter for button.

Upvotes: 36

Views: 180847

Answers (4)

Ahmed_mag
Ahmed_mag

Reputation: 260

Try this:

 public class MyVmBase : INotifyPropertyChanged
{
  private ICommand _clickCommand;
   public ICommand ClickCommand
    {
        get
        {
            return _clickCommand ?? (_clickCommand = new CommandHandler( MyAction));
        }
    }
    
       public void MyAction(object message)
    {
        if(message == null)
        {
            Notify($"Method {message} not defined");
            return;
        }
        switch (message.ToString())
        {
            case "btnAdd":
                {
                    btnAdd_Click();
                    break;
                }

            case "BtnEdit_Click":
                {
                    BtnEdit_Click();
                    break;
                }

            default:
                throw new Exception($"Method {message} not defined");
                break;
        }
    }
}

  public class CommandHandler : ICommand
{
    private Action<object> _action;
    private Func<object, bool> _canExecute;

    /// <summary>
    /// Creates instance of the command handler
    /// </summary>
    /// <param name="action">Action to be executed by the command</param>
    /// <param name="canExecute">A bolean property to containing current permissions to execute the command</param>
    public CommandHandler(Action<object> action, Func<object, bool> canExecute)
    {
        if (action == null) throw new ArgumentNullException(nameof(action));
        _action = action;
        _canExecute = canExecute ?? (x => true);
    }
    public CommandHandler(Action<object> action) : this(action, null)
    {
    }

    /// <summary>
    /// Wires CanExecuteChanged event 
    /// </summary>
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    /// <summary>
    /// Forcess checking if execute is allowed
    /// </summary>
    /// <param name="parameter"></param>
    /// <returns></returns>
    public bool CanExecute(object parameter)
    {
        return _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _action(parameter);
    }
    public void Refresh()
    {
        CommandManager.InvalidateRequerySuggested();
    }
}

And in xaml:

     <Button
    Command="{Binding ClickCommand}"
    CommandParameter="BtnEdit_Click"/>

Upvotes: 2

John Zhu
John Zhu

Reputation: 1099

Just using Data Binding syntax. For example,

<Button x:Name="btn" 
         Content="Click" 
         Command="{Binding ClickCmd}" 
         CommandParameter="{Binding ElementName=btn,Path=Content}" /> 

Not only can we use Data Binding to get some data from View Models, but also pass data back to View Models. In CommandParameter, must use ElementName to declare binding source explicitly.

Upvotes: 17

Mark Feldman
Mark Feldman

Reputation: 16119

"ViewModel" implies MVVM. If you're doing MVVM you shouldn't be passing views into your view models. Typically you do something like this in your XAML:

<Button Content="Edit" 
        Command="{Binding EditCommand}"
        CommandParameter="{Binding ViewModelItem}" >

And then this in your view model:

private ViewModelItemType _ViewModelItem;
public ViewModelItemType ViewModelItem
{
    get
    {
        return this._ViewModelItem;
    }
    set
    {
        this._ViewModelItem = value;
        RaisePropertyChanged(() => this.ViewModelItem);
    }
}

public ICommand EditCommand { get { return new RelayCommand<ViewModelItemType>(OnEdit); } }
private void OnEdit(ViewModelItemType itemToEdit)
{
    ... do something here...
}

Obviously this is just to illustrate the point, if you only had one property to edit called ViewModelItem then you wouldn't need to pass it in as a command parameter.

Upvotes: 73

Justin CI
Justin CI

Reputation: 2741

If you are that particular to pass elements to viewmodel You can use

 CommandParameter="{Binding ElementName=ManualParcelScanScreen}"

Upvotes: 8

Related Questions