web-dev-qa-db-ja.com

コードビハインドからコマンドを呼び出す

そのため、私は探し回っていましたが、これを行う方法を正確に見つけることはできません。 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>

これを行う簡単な方法があると確信していますが、私の人生ではそれを理解することはできません。

61
Kevin DiTraglia

さて、DataContextが既に設定されている場合、キャストしてコマンドを呼び出すことができます。

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

(必要に応じてパラメーターを変更)

123
H.B.

序文:要件について詳しく知ることなく、ロード時にコードビハインドからコマンドを実行するのはコードのにおいのようです。より良い方法、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);
} 

もう一度-より良い方法を見つけてみてください...

5
Wonko the Sane

共有したい、よりコンパクトなソリューションがあります。 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
Alain

また、MessaginCenter.Subscribeにコードを埋め込み、MessagingCenterモデルで作業することもできます。 Commandプロパティを持つ表示ボタンをクリックする代わりに、コードビハインドから何かを実行するだけであれば、それは私には完璧に機能しました。

私はそれが誰かを助けることを願っています。

0
Joilson Cardoso