C# 从背后的代码调用命令

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10126968/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 12:32:32  来源:igfitidea点击:

Call Command from Code Behind

c#wpfxamldata-bindingcommand

提问by Kevin DiTraglia

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

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

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

环顾四周,我似乎无法在任何地方找到此语法。我是否需要先在 xaml 中绑定命令才能引用它?我注意到用户控件中的命令绑定选项不会让您像在按钮之类的东西中那样绑定命令......

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

我确信有一种简单的方法可以做到这一点,但我终生无法弄清楚。

采纳答案by H.B.

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

好吧,如果 DataContext 已经设置,你可以转换它并调用命令:

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

(Change parameter as needed)

(根据需要更改参数)

回答by Alain

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

回答by 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.

前言:在不了解您的需求的情况下,在加载时从代码隐藏执行命令似乎是一种代码味道。必须有更好的方法,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...

再次 - 尝试找到更好的方法......

回答by Stefan Vasiljevic

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.

我有一个更紧凑的解决方案要分享。因为我经常在我的 ViewModel 中执行命令,我厌倦了编写相同的 if 语句。所以我写了一个 ICommand 接口的扩展。

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)

PS 不要忘记也包含 ICommandHelper 的命名空间。(就我而言,它是 SharedViewModels.Helpers)

回答by Joilson Cardoso

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.

您还可能将代码嵌入到任何 MessaginCenter.Subscribe 中并使用 MessagingCenter 模型。如果您只想从后面的代码中执行某些操作,而不是单击具有 Command 属性的视图按钮,那么它对我来说效果很好。

I hope it helps someone.

我希望它可以帮助某人。