提供公共方法并绑定操作还不够吗
从视图直接到这个公共方法?为什么 ICommand 存在?
您不能绑定到 xaml 中的方法。你需要一个对象。因此,您需要将方法包装到一个对象中。
这是 UI 中的一种常见模式,即某些操作并非始终可用。在登录表单中,登录操作仅在您输入用户名时才可用。在 MS Word 中,复制或剪切操作仅在您选择某些内容时才可用,否则按钮将被禁用且键盘快捷键无效
- 这是一种常见的模式,可以使用不同的参数调用该命令。
普通事件处理程序不满足这些要求,但ICommand 服务器正是这些目的:
public interface ICommand
{
void Execute(object parameter);
bool CanExecute(object parameter);
event EventHandler CanExecuteChanged;
}
- 它将方法包装到一个对象中
- 它表示命令是否可用,因此 UI 组件(通常是按钮或菜单项)可以反映它
- 此外,它会通知 UI 组件该命令的可用性已更改,以便 UI 可以反映它。
现在,让我们考虑复制和粘贴场景。使用 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,后来又想添加它怎么办。然后,您必须在每次出现 Paste 调用时添加 CanPaste 绑定。我向你保证,你会在某个地方忘记它。
现在,如果您在 WPF 中执行此操作:
<Button Content="Paste" Click="Call_ViewModel_Paste" />
//in codebehind:
void Call_ViewModel_Paste(oobject sender, RoutedEventArgs e)
{
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 那样优雅