Не было бы достаточно, чтобы предоставить общедоступные методы и связать действие с представлением непосредственно на этот общедоступный метод? Почему ICommand существует?
вы не можете привязать к методу в XAML. Вам нужен объект. Поэтому вам нужно обернуть метод к объекту.
это общий шаблон в пользовательском интерфейсе, что некоторые действия недоступны все время. В форме «Вход» действие «Вход» становится доступным только при вводе имени пользователя. В MS Word действия «Копировать» или «Вырезание» становятся доступными только при выборе чего-либо, в противном случае кнопки отключены, а сочетания клавиш неактивны
- Это общий шаблон, который может вызываться с различными параметрами.
Plain eventhandlers не отвечает этим требованиям, но ICommand
серверы именно эти цели:
public interface ICommand
{
void Execute(object parameter);
bool CanExecute(object parameter);
event EventHandler CanExecuteChanged;
}
- Он оборачивает метод объекта
- Это говорит ли команда доступна или нет, так компонент пользовательского интерфейса (обычно кнопка или элемент меню) может отражать его
- Кроме того, он уведомляет компоненты пользовательского интерфейса о том, что доступность команды была изменена, поэтому пользовательский интерфейс может отображать и т.д.
Теперь давайте рассмотрим Копировать & Вставить сценарий. Использование 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
* «привязать действие из представления непосредственно к этому общедоступному методу» * - это то, что делает «ICommand», а также сообщает «View» всякий раз, когда выполняется команда ** **. Взгляните на ['DelegateCommand'] (https://wpftutorial.net/DelegateCommand.html), это упрощает. – Sinatr
Некоторые среды MVVM, такие как Caliburn.Micro, используют соглашения об именах для привязки методов к просмотру элементов * без * ICommand. –
С помощью * прикрепленных поведений * (чистый MVVM) можно легко добавить собственную функциональность: вы можете подписаться на определенные события просмотра (вы можете сделать это в кодовом замке View, но это было бы грязно MVVM), чтобы вызвать определенные методы ViewModel (напрямую, через интерфейс или с помощью отражения). «ICommand» был минимальным, что нужно WPF, а именно: он решает проблему, когда элементы меню/кнопки становятся недоступными, например. для сценария 'Copy' /' Paste'. Больше ничего. Фактически 'ButtonBase.Command' может быть простым обработчиком событий Click, вы можете сразу же вызвать метод ViewModel. – Sinatr