Call Command from Code Behind

C#WpfXamlData BindingCommand

C# Problem Overview


So I've been searching around and cannot find out exactly how to do this. I'm creating a user control using MVVM and would like to run a command on the 'Loaded' event. I realize this requires a little bit of code behind, but I can't quite figure out what's needed. The command is located in the ViewModel, which is set as the datacontext of the view, but I'm not sure exactly how to route this so I can call it from the code behind of the loaded event. Basically what I want is something like this...

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    //Call command from viewmodel
}

Looking around I can't seem to find the syntax for this anywhere. Do I need to bind the command in the xaml first to be able to reference it? I notice the command bindings option within a user control will not let you bind commands as you can within something like a button...

<UserControl.CommandBindings>
    <CommandBinding Command="{Binding MyCommand}" /> <!-- Throws compile error -->
</UserControl.CommandBindings>

I'm sure there's a simple way to do this, but I can't for the life of me figure it out.

C# Solutions


Solution 1 - C#

Well, if the DataContext is already set you could cast it and call the command:

var viewModel = (MyViewModel)DataContext;
if (viewModel.MyCommand.CanExecute(null))
    viewModel.MyCommand.Execute(null);

(Change parameter as needed)

Solution 2 - C#

Preface: Without knowing more about your requirements, it seems like a code smell to execute a command from code-behind upon loading. There has to be a better way, MVVM-wise.

But, if you really need to do it in code behind, something like this would probably work (note: I cannot test this at the moment):

private void UserControl_Loaded(object sender, RoutedEventArgs e)     
{
    // Get the viewmodel from the DataContext
    MyViewModel vm = this.DataContext as MyViewModel;

    //Call command from viewmodel     
    if ((vm != null) && (vm.MyCommand.CanExecute(null)))
        vm.MyCommand.Execute(null);
} 

Again - try to find a better way...

Solution 3 - C#

I have a more compact solution that I want to share. Because I often execute commands in my ViewModels, I got tired of writing the same if statement. So I wrote an extension for ICommand interface.

using System.Windows.Input;

namespace SharedViewModels.Helpers
{
    public static class ICommandHelper
    {
        public static bool CheckBeginExecute(this ICommand command)
        {
            return CheckBeginExecuteCommand(command);
        }

        public static bool CheckBeginExecuteCommand(ICommand command)
        {
            var canExecute = false;
            lock (command)
            {
                canExecute = command.CanExecute(null);
                if (canExecute)
                {
                    command.Execute(null);
                }
            }

            return canExecute;
        }
    }
}

And this is how you would execute command in code:

((MyViewModel)DataContext).MyCommand.CheckBeginExecute();

I hope this will speed up your development just a tiny bit more. :)

P.S. Don't forget to include the ICommandHelper's namespace too. (In my case it is SharedViewModels.Helpers)

Solution 4 - C#

Try this:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    //Optional - first test if the DataContext is not a MyViewModel
    if( !this.DataContext is MyViewModel) return;
    //Optional - check the CanExecute
    if( !((MyViewModel) this.DataContext).MyCommand.CanExecute(null) ) return;
    //Execute the command
    ((MyViewModel) this.DataContext).MyCommand.Execute(null)
}

Solution 5 - C#

To call a command in code behind, you can use this code line

e.g.: Call a Button command

Button.Command?.Execute(Button.CommandParameter);

Solution 6 - C#

You also might have embedded your code in any MessaginCenter.Subscribe and work with MessagingCenter model. If you intend only execute something from code behind instead of clicking in a view button with Command property, it worked perfectly to me.

I hope it helps someone.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKevin DiTragliaView Question on Stackoverflow
Solution 1 - C#H.B.View Answer on Stackoverflow
Solution 2 - C#Wonko the SaneView Answer on Stackoverflow
Solution 3 - C#Stefan VasiljevicView Answer on Stackoverflow
Solution 4 - C#AlainView Answer on Stackoverflow
Solution 5 - C#lukaView Answer on Stackoverflow
Solution 6 - C#Joilson CardosoView Answer on Stackoverflow