WPF 之命令(七)
一、前言
? 事件的作用是发布和传播一些消息,消息送达接收者,事件的使命也就完成了,至于消息响应者如何处理发送来的消息并不做规定,每个接收者可以使用自己的行为来响应事件。即事件不具有约束力。
? 命令就有约束力,不仅可以约束代码,还可以约束步骤逻辑。
二、WPF 的 命令系统
? WPF 中,命令系统由以下元素构成:
-
命令(Command):实现 ICommand 接口。表示一个程序任务,并可跟踪该任务是否完成。
-
命令源(Commannd Source):命令的发送者。需实现 ICommandSource 接口。
-
命令目标(Command Target):命令的接收者。需实现 IInputElment 接口的类。
-
命令关联(Command Binding):负责把外围逻辑和命令关联起来。
? WPF中提供了一组已定义命令,命令包括以下类:、、、 以及。 这些类提供诸如 、、、、 和 等命令。下面我们使用 ApplicationCommands 进行以下测试:
// 命令执行具体操作
private void CommandBinding_OnExecuted(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show($"New 命令被触发了,命令源是:{e.Source}");
}
? 点击按钮后,输出结果为:
New 命令被触发了,命令源是:System.Windows.Controls.Button: New
三、自定义命令
? 例如,我们需要增加一个数据的查库与上传数据操作,那么需要实现 Query 和 Insert 命令,为了能够直接供 UI 使用,我们声明 RoutedUICommand 命令,具体如下:
public class DatabaseCommands
{
private static RoutedUICommand _query;
private static RoutedUICommand _insert;
static DatabaseCommands()
{
InputGestureCollection inputs = new InputGestureCollection();
inputs.Add(new KeyGesture(Key.Q ,ModifierKeys.Control, "Ctrl+R"));
_query = new RoutedUICommand(
"Query", "Query", typeof(DatabaseCommands), inputs);
inputs.Add(new KeyGesture(Key.D, ModifierKeys.Control, "Ctrl+D"));
_insert = new RoutedUICommand(
"Add", "Add", typeof(DatabaseCommands), inputs);
}
public static RoutedUICommand Query
{
get { return _query; }
}
public static RoutedUICommand Insert
{
get { return _insert; }
}
}
? 命令实现与绑定到 UI 上的操作如下:
// 命令执行具体操作
private void DatabaseCommandsQuery_OnExecuted(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show($"Query 命令被触发了,命令源是:{e.Source}");
}
private void DatabaseCommandsAdd_OnExecuted(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show($"Add 命令被触发了,命令源是:{e.Source}");
}
? 当我们点击 Query 和 Insert 操作时,分别执行对应的操作。上述例子中,Command 的执行代码是在 XAML 中声明的,那我们把命令的执行代码进行代码后置,且为了满足不同的条件,我们声明一个 RelayCommand 基类进行封装,具体如下:
///
/// The base implementation of a command.
///
abstract class CommandBase : ICommand
{
///
/// Occurs when changes occur that affect whether or not the command should execute.
///
public event EventHandler CanExecuteChanged
{
add { System.Windows.Input.CommandManager.RequerySuggested += value; }
remove { System.Windows.Input.CommandManager.RequerySuggested -= value; }
}
///
/// Raises the event.
///
public void OnCanExecuteChanged()
{
System.Windows.Input.CommandManager.InvalidateRequerySuggested();
}
///
/// Defines the method that determines whether the command can execute in its current state.
///
/// Data used by the command. If the command does not require data to be passed, this object can be set to null.
///
/// true if this command can be executed; otherwise, false.
///
public virtual bool CanExecute(object parameter)
{
return true;
}
///
/// Defines the method to be called when the command is invoked.
///
/// Data used by the command. If the command does not require data to be passed, this object can be set to null.
public void Execute(object parameter)
{
if (!CanExecute(parameter))
{
return;
}
OnExecute(parameter);
}
///
/// Executes the command.
///
/// The parameter.
protected abstract void OnExecute(object parameter);
}
///
/// The command that relays its functionality by invoking delegates.
///
class RelayCommand : CommandBase
{
private readonly Action
? 然后,我们实现一个示例,点击 Clear 按钮时,清空 TextBox 中的所有内容,那么需要声明一个 Model 和 ViewModel ,具体实现可以阅读 :
class Student
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
class MainWindowVM : NotifyProperty
{
private Student _student;
public Student Student
{
get => _student;
set => SetProperty(ref _student, value);
}
public ICommand Clear { get; set; }
private void ClearCommand(object args)
{
Student = new Student();
}
public MainWindowVM()
{
_student = new Student()
{
Id = "01",
Name = "Dwayne",
Email = "974608610@qq.com",
Phone = "180888888888",
};
Clear=new RelayCommand(ClearCommand,null);
}
}
? 最后,我们把该 ViewModel 绑定到 XAML 上,具体如下:
? 当我们点击 Clear 按钮时,所有的 TextBox 就被清空了显示。其实,上述这个例子就是一个简单的 MVVM 示例,它让逻辑代码和 UI 完全分离。对于 Command 来说,当我们要执行 TextChanged 事件时,需要添加 “System.Windows.Interactivity” ,然后在 XAML 中添加如下引用:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
当我们改变该文本框的内容时,也可执行 Clear 命令。
原文:https://www.cnblogs.com/dongweian/p/14389484.html