Вызов команды из кода позади


Так что я искал вокруг и не могу точно выяснить, как это сделать. Я создаю пользовательский элемент управления с помощью MVVM и хотел бы запустить команду на 'Loaded' событие. Я понимаю, что для этого требуется немного кода, но я не могу понять, что нужно. Команда находится в ViewModel, который установлен как datacontext представления, но я не уверен точно, как маршрутизировать это, чтобы я мог вызвать его из кода позади загруженного события. В основном то, что я хочу что-то вроде этого...

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

оглядываясь вокруг, я не могу найти синтаксис для этого нигде. Нужно ли сначала привязать команду в xaml, чтобы иметь возможность ссылаться на нее? Я замечаю, что опция привязки команд в пользовательском элементе управления не позволит вам связывать команды, как вы можете в чем-то вроде кнопки...

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

Я уверен, что есть простой способ сделать это, но я не могу за жизнь мне выяснить это.

5 54

5 ответов:

Ну, если DataContext уже установлен, вы можете бросить его и вызвать команду:

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

(изменить параметр по мере необходимости)

предисловие: не зная больше о ваших требованиях, кажется, что запах кода выполняет команду из кода позади При загрузке. Должен быть лучший способ, MVVM-wise.

но, если вам действительно нужно сделать это в коде, что-то вроде этого, вероятно, работать (примечание: Я не могу проверить это на данный момент):

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

еще раз-попробуйте найти лучший способ...

попробуйте это:

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

у меня есть более компактное решение, которым я хочу поделиться. Поскольку я часто выполняю команды в своих ViewModels, я устал писать один и тот же оператор 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();

Я надеюсь, что это ускорит ваше развитие только немного больше. :)

P. S. Не забудьте включить тоже имен ICommandHelper по. (В моем случае это SharedViewModels.Помощники)

вы также могли бы встроить свой код в любой MessaginCenter.Подписка и работа с моделью MessagingCenter. Если вы намереваетесь только выполнить что-то из кода позади, а не нажимать на кнопку просмотра со свойством Command, это отлично сработало для меня.

Я надеюсь, что это поможет кому-то.