提供公共方法并将视图中的操作直接绑定到此公共方法是不够的?为什么ICommand存在?
你无法绑定到xaml中的方法.你需要一个物体.因此,您需要将方法包装到对象.
它是UI中的常见模式,某些操作始终不可用.在登录表单中,只有在输入用户名时,"登录"操作才可用.在MS Word中,只有在您选择某些内容时,"复制"或"剪切"操作才可用,否则按钮将被禁用,键盘快捷键将处于非活动状态
普通的事件处理程序不符合这些要求,但ICommand服务器完全符合以下目的:
public interface ICommand
{
void Execute(object parameter);
bool CanExecute(object parameter);
event EventHandler CanExecuteChanged;
}
Run Code Online (Sandbox Code Playgroud)
现在,让我们考虑复制和粘贴方案.使用ICommand标记可能如下所示:
<Button Content="Paste" Command="{Binding PasteCommand}" />
<MenuItem Header="Paste" Command="{Binding PasteCommand}" />
Run Code Online (Sandbox Code Playgroud)
public ICommand PasteCommand {get;} = new DelegateCommand(Paste, () => Clipboard != null);
Run Code Online (Sandbox Code Playgroud)
没有它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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,它不仅更加冗长,而且还违反了DRY原则.每次要使用该命令时都需要指定Paste和CanPaste绑定.如果您在没有CanPaste的情况下开始,之后又想添加它,该怎么办?然后,您必须在每次Paste调用时添加CanPaste绑定.我向你保证,你会在某个地方忘记它.
现在,如果你在WPF中这样做了:
<Button Content="Paste" Click="Call_ViewModel_Paste" />
Run Code Online (Sandbox Code Playgroud)
//in codebehind:
void Call_ViewModel_Paste(oobject sender, RoutedEventArgs e)
{
ViewModel.Paste();
}
Run Code Online (Sandbox Code Playgroud)
或者最终:
<Button Content="Paste">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:CallMethodAction MethodName="Paste" TargetObject="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Run Code Online (Sandbox Code Playgroud)
这两种方法都是正确的,它们遵循MVVM原则并且无需ICommand即可工作,但正如您所看到的,它们都不如 ICommand