2017-02-08 11 views
1

В приложении, использующем mvvm-подход, довольно часто встречается то, что ViewModel предоставляет одну или несколько команд -properties. Эти свойства часто имеют тип ICommand или DelegateCommand или что-то в этом роде.В чем причина ICommand в Mvvm?

Я не понимаю, почему нам нужен такой подход в приложении mvvm. Было бы недостаточно, чтобы предоставить общедоступные методы и связать действие с представлением непосредственно с этим общедоступным методом?

Почему существует ICommand?

+3

* «привязать действие из представления непосредственно к этому общедоступному методу» * - это то, что делает «ICommand», а также сообщает «View» всякий раз, когда выполняется команда ** **. Взгляните на ['DelegateCommand'] (https://wpftutorial.net/DelegateCommand.html), это упрощает. – Sinatr

+1

Некоторые среды MVVM, такие как Caliburn.Micro, используют соглашения об именах для привязки методов к просмотру элементов * без * ICommand. –

+0

С помощью * прикрепленных поведений * (чистый MVVM) можно легко добавить собственную функциональность: вы можете подписаться на определенные события просмотра (вы можете сделать это в кодовом замке View, но это было бы грязно MVVM), чтобы вызвать определенные методы ViewModel (напрямую, через интерфейс или с помощью отражения). «ICommand» был минимальным, что нужно WPF, а именно: он решает проблему, когда элементы меню/кнопки становятся недоступными, например. для сценария 'Copy' /' Paste'. Больше ничего. Фактически 'ButtonBase.Command' может быть простым обработчиком событий Click, вы можете сразу же вызвать метод ViewModel. – Sinatr

ответ

2

Не было бы достаточно, чтобы предоставить общедоступные методы и связать действие с представлением непосредственно на этот общедоступный метод? Почему ICommand существует?

  1. вы не можете привязать к методу в XAML. Вам нужен объект. Поэтому вам нужно обернуть метод к объекту.

  2. это общий шаблон в пользовательском интерфейсе, что некоторые действия недоступны все время. В форме «Вход» действие «Вход» становится доступным только при вводе имени пользователя. В MS Word действия «Копировать» или «Вырезание» становятся доступными только при выборе чего-либо, в противном случае кнопки отключены, а сочетания клавиш неактивны

  3. Это общий шаблон, который может вызываться с различными параметрами.

Plain eventhandlers не отвечает этим требованиям, но ICommand серверы именно эти цели:

public interface ICommand 
{ 
    void Execute(object parameter); 
    bool CanExecute(object parameter); 
    event EventHandler CanExecuteChanged; 
} 
  1. Он оборачивает метод объекта
  2. Это говорит ли команда доступна или нет, так компонент пользовательского интерфейса (обычно кнопка или элемент меню) может отражать его
  3. Кроме того, он уведомляет компоненты пользовательского интерфейса о том, что доступность команды была изменена, поэтому пользовательский интерфейс может отображать и т.д.

Теперь давайте рассмотрим Копировать & Вставить сценарий. Использование ICommand разметка может выглядеть следующим образом:

<Button Content="Paste" Command="{Binding PasteCommand}" /> 
<MenuItem Header="Paste" Command="{Binding PasteCommand}" /> 
public ICommand PasteCommand {get;} = new DelegateCommand(Paste,() => Clipboard != null); 

Как это будет выглядеть без ICommand? Для того, чтобы сделать его проще, давайте рассмотрим, что XAML позволит связываться с методами:

<Button Content="Paste" Click="{Binding Paste}" IsEnabled="{Binding CanPaste}" /> 
<MenuItem Header="Paste" Click="{Binding Paste}" IsEnabled="{Binding CanPaste}"/> 

public void Paste() {....} 

private bool _canPaste; 
public bool CanPaste 
{ 
    get { return _canPaste } 
    set 
    { 
     if (_canPaste != value) 
     { 
      _canPaste = value; 
      OnNotifyPropertyChanged(nameof(CanPaste); 
     } 
    } 
} 

, как вы можете видеть, не только это более многословным, но это также нарушение DRY принципа. Вы должны указывать как привязки Paste, так и CanPaste каждый раз, когда хотите использовать команду. Что делать, если вы начали без CanPaste, и позже вы хотели его добавить. Затем вам нужно будет добавить привязку CanPaste к любому вхождению вызова Paste. Я гарантирую вам, что вы забудете его где-нибудь.

Теперь, если вы сделали это в WPF:

<Button Content="Paste" Click="Call_ViewModel_Paste" /> 
//in codebehind: 
void Call_ViewModel_Paste(oobject sender, RoutedEventArgs e) 
{ 
    ViewModel.Call_ViewModel_Paste(); 
} 

или в конечном счете:

<Button Content="Paste"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="Click"> 
      <ei:CallMethodAction MethodName="Paste" TargetObject="{Binding}"/> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</Button> 

Оба подхода являются правильными, они следуют MVVM основой работы наноэлектронных и работает без ICommand, но как вы можете видеть, нет такого элегантного, как ICommand

2

Не было бы достаточно, чтобы предоставить общедоступные методы и связать действие с представлением непосредственно этому общедоступному методу?

Как бы вы, например, вызвали открытый метод, когда нажал Button на вид?

Ответ на этот вопрос заключается в том, что вы связываете свойство Command объекта Button с атрибутом ICommand вида модели просмотра, который вызывает этот метод для вас. Это основная причина, по которой любые действия, которые определяют модель модели, отображаются с помощью команд.

Команда - это не что иное, как объект, реализующий интерфейс System.Windows.Input.ICommand и инкапсулирующий код для действия, которое необходимо выполнить.

Для получения дополнительной информации о концепции, пожалуйста, обратитесь к следующим ссылкам.

https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/ https://msdn.microsoft.com/en-us/magazine/dn237302.aspx

+0

* »Команда - это не что иное, как объект, который ... инкапсулирует код для действия, которое нужно выполнить.« * - Но это именно то, что он * не *, не так ли? Команда является всего лишь маркером сортировки, фактическое действие происходит из команды * binding *. – Joey

+0

Вы не используете System.Windows.Input.CommandBinding в MVVM.Вы привязываетесь к свойству модели представления, которая возвращает объект ICommand, а затем метод Execute этого объекта ICommand вызывается, когда вы, например, нажимаете кнопку в представлении. – mm8

+0

Как это ответить * почему * Команды WPF работают так, как они делают? Похоже, что OP спрашивает, почему мы не можем написать '{Binding MethodName}' вместо '{Binding CommandObject}'. –

1

В MVVM вы пытаетесь избежать «код позади» (это код в файле MyView.cs), чтобы избежать тесной связи View, ViewModel и модель.

В MFC вы только что зарегистрировали обработчик событий (который по-прежнему возможен в WPF), но в MVVM существует возможность просто привязать ICommand, которая будет выполнена вместо запуска события.

+2

Вы можете привязать View к методу в ViewModel. Фактически, вы можете сделать это, используя 'CallMethodAction' в xaml. Так что это не совсем ответ, почему нам нужен ICommand – Liero

+0

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