从代码后呼叫指挥部

所以我一直在四处寻找,但找不到确切的方法。我正在创建一个使用 MVVM 的用户控件,并希望运行一个命令的“加载”事件。我知道这需要一些代码,但我不知道需要什么。该命令位于 ViewModel 中,它被设置为视图的数据上下文,但是我不确定如何路由它,以便从加载事件后面的代码调用它。基本上我想要的是这样的东西..。

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

环顾四周,我似乎在任何地方都找不到这个词的语法。我是否需要先绑定 xaml 中的命令才能引用它?我注意到用户控件中的命令绑定选项不允许您像在按钮中那样绑定命令..。

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

我相信有一个简单的方法,但我无论如何也想不出来。

95014 次浏览

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

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)

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

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.

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

e.g.: Call a Button command

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