Call Command from Code Behind

坚强是说给别人听的谎言 提交于 2019-11-29 22:46:42
H.B.

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)

Wonko the Sane

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...

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)
}

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)

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!