我觉得你在这里混淆了不同的事情。该 ICommand Interface 用于将UI事件绑定到设计模式中使用的代码 MVVM 。该 Command Design Pattern 你正在尝试实现的是一个状态架构 撤消动作 像按钮按下。
ICommand Interface
Command Design Pattern
CanExecute
许多答案突出了使用委托的ICommand接口的有用实现。您甚至可以通过绑定到如下所示的模型更改来进一步操作,或者如果您愿意,可以随意过滤。这可以用于重新评估命令是否应该能够基于模型状态触发,因为这直接与按钮的“启用”状态相关联。
public class ObservableCommand<T> : ICommand where T : System.ComponentModel.INotifyPropertyChanged { Predicate<object> _predicate; Action<object> _execute; public ObservableCommand(T model, Action<object> execute, Predicate<object> predicate) { model.PropertyChanged += ModelChanged; _execute = execute; _predicate = predicate; } public event EventHandler CanExecuteChanged; private void ModelChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { CanExecuteChanged?.Invoke(this, EventArgs.Empty); } public bool CanExecute(object parameter) { return _predicate(parameter); } public void Execute(object parameter) { _execute(parameter); } }
关于撤消操作的问题。您当然可以使用命令来调用它,但是跟踪对象的状态是更棘手的部分。你可以使用 纪念品设计模式 并将您的命令绑定到恢复状态功能。这是过于简单化,但一直是我过去所做的实施的核心。
public class Memento<T> { public Memento(T startState) { this.State = startState; this.OriginalState = startState; } public T State { get; set; } public T OriginalState { get; } public void RestorOriginalState() { State = OriginalState; } }
首先,这些命令是MVVM模式的一部分,您应该首先阅读它。
C#中的接口不提供任何功能,它们仅描述继承此接口的类应该如何工作。如果您希望班级做某事,您不应该将这些方法留空。
WPF中的命令代表了一种稍后将传输逻辑的框架。命令的最合理用途是将它们绑定到按钮。
ICommand实现示例:
public class RelayCommand : ICommand { private readonly Action<object> execute; private readonly Func<object, bool> canExecute; public event EventHandler CanExecuteChanged { add => CommandManager.RequerySuggested += value; remove => CommandManager.RequerySuggested -= value; } public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null) { this.execute = execute; this.canExecute = canExecute; } public bool CanExecute(object parameter) { return canExecute == null || canExecute(parameter); } public void Execute(object parameter) { execute(parameter); } }
命令使用示例:
public static RelayCommand NavigateToSignInPage => new RelayCommand( actionParameter => Application.Instance.Navigation.NavigateTo(new LoginForm())); public static RelayCommand NavigateToSignUpPage => new RelayCommand( actionParameter => Application.Instance.Navigation.NavigateTo(new RegistrationForm())); public static RelayCommand NavigateToStartPage => new RelayCommand( actionParameter => Application.Instance.Navigation.NavigateTo(new StartPage())); public static RelayCommand NavigateBack => new RelayCommand( actionParameter => Application.Instance.Navigation.NavigateBack(), actionPossibilityParameter => Application.Instance.Navigation.BackNavigationPossible);
命令绑定示例: 在视图(xaml)中:
<Button x:Name="CancelButton" Content="Cancel" Command="{Binding CancelCommand}" Grid.Row="2" IsCancel="True" HorizontalAlignment="Left" Margin="44,0,0,0" Width="118" Height="23" VerticalAlignment="Center" />
在ViewModel中:
public RelayCommand CancelCommand => NavigationCommands.NavigateBack;