Вызов команды из кода
Итак, я искал и не могу точно узнать, как это сделать. Я создаю пользовательский элемент управления с помощью 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>
Я уверен, что есть простой способ сделать это, но я не могу для жизни понять это.
Ответы
Ответ 1
Ну, если DataContext уже установлен, вы можете его набросить и вызвать команду:
var viewModel = (MyViewModel)DataContext;
if (viewModel.MyCommand.CanExecute(null))
viewModel.MyCommand.Execute(null);
(При необходимости измените параметр)
Ответ 2
Предисловие: не зная больше о ваших требованиях, кажется, что это запах кода для выполнения команды из кода после загрузки. Должен быть лучший способ, 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);
}
Снова - попытайтесь найти лучший способ...
Ответ 3
Попробуйте следующее:
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)
}
Ответ 4
У меня есть более компактное решение, которое я хочу поделиться. Поскольку я часто выполняю команды в своих моделях 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.Helpers)
Ответ 5
Вы также могли бы встроить свой код в любой MessaginCenter.Subscribe и работать с моделью MessagingCenter. Если вы намерены выполнять только что-то из кода, вместо того, чтобы щелкнуть кнопкой просмотра с помощью свойства Command, это сработало отлично для меня.
Надеюсь, это поможет кому-то.