2012-04-12 4 views
48

Итак, я искал и не могу точно узнать, как это сделать. Я создаю пользовательский элемент управления с помощью 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> 

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

ответ

101

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

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

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

+0

Да, это именно то, что мне нужно, я знал, что есть простой способ. Благодаря! –

+0

@KDiTraglia: Добро пожаловать, рад, что это помогло. –

+0

Вы должны проверить, имеет ли viewModel значение null, прежде чем пытаться получить доступ к MyCommand. Я знаю, что мое решение не так, но ваш - это принятый ответ, поэтому он, вероятно, должен быть там. – Alain

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

Вы не должны вызывать команду, не гарантируя ее выполнение в первую очередь. –

+0

Если вы используете CanExecute, чтобы определить, может ли пользователь выполнить его (т. Е. Привязка к включенному состоянию кнопки), в этом нет ничего плохого. – Alain

+3

С помощью кнопки элемент управления гарантирует, что команда никогда не выполняется небрежно, если вы ее вручную запускаете, вам нужно позаботиться об этом самостоятельно. –

3

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

Опять же - попытаться найти лучший способ ...

+1

При поиске по теме действительно нет никакого простого способа, и общий консенсус, который я видел, - это небольшой код, который никогда не убивал никого. –

+1

@KDiTraglia - правда, но, вообще говоря, «маленький код позади» обычно относится к действиям, которые влияют только на сам вид (т. Е. Такие вещи, как выбор всего текста в текстовом поле, когда он получает фокус). Здесь вы напрямую взаимодействуете с ViewModel из кода кода View, который нарушает принцип MVVM. –

1

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

Смежные вопросы