从代码隐藏中调用命令

问题描述 投票:0回答:7

所以我一直在四处寻找,但找不到确切的方法。我正在使用 MVVM 创建用户控件,并希望在“Loaded”事件上运行命令。我意识到这需要一些代码,但我不太清楚需要什么。该命令位于 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>

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

c# wpf xaml data-binding command
7个回答
175
投票

好吧,如果 DataContext 已经设置,您可以投射它并调用命令:

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

(根据需要更改参数)


10
投票

前言:在不了解更多关于您的需求的情况下,在加载时从代码隐藏中执行命令似乎有一种代码味道。必须有更好的方法,MVVM 方面。

但是,如果您确实需要在代码后面执行此操作,类似这样的操作可能会起作用(注意:我目前无法测试这一点):

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

再次尝试寻找更好的方法...


2
投票

我有一个更紧凑的解决方案想要分享。因为我经常在 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;
        }
    }
}

这就是在代码中执行命令的方式:

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

我希望这能加快你的发展速度。 :)

附注不要忘记也包含 ICommandHelper 的命名空间。 (在我的例子中是 SharedViewModels.Helpers)


1
投票

试试这个:

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

1
投票

要在代码后面调用命令,可以使用此代码行

例如: 调用按钮命令

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

0
投票

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

我希望它对某人有帮助。


0
投票

其实你可以在视图后面的代码中创建一个命令,并在

App.xaml
中绑定它。

public static readonly DependencyProperty UpdateCommandProperty =
    DependencyProperty.Register(
        nameof(UpdateCommand),
        typeof(ICommand),
        typeof(View),
        new PropertyMetadata(null));

public ICommand UpdateCommand
{
    get => GetValue(UpdateCommandProperty) as ICommand;
    set => SetValue(UpdateCommandProperty, value);
}

public Void Update()
{
    UpdateCommand?.Execute(this);
}
<Application.Resources>

    <ResourceDictionary>

        <DataTemplate DataType="{x:Type viewmodels:ViewModel}">
            <views:View UpdateCommand="{Binding UpdateCommand}" />
        </DataTemplate>

    </ResourceDictionary>

</Application.Resources>
© www.soinside.com 2019 - 2024. All rights reserved.