什么是Command?先看下微软官方的说明:
Commanding is an input mechanism in Windows Presentation Foundation (WPF) which provides input handling at a more semantic level than device input. Examples of commands are the Copy, Cut, and Paste operations found on many applications.
命令是Windows Presentation Foundation(WPF)中的一种输入机制,它提供比设备输入更多的语义级别的输入处理。命令示例包括在许多应用程序中发现的“复制”,“剪切”和“粘贴”操作。
MainWindows.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <Window x:Class ="UsingDelegateCommands.Views.MainWindow" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism ="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel ="True" Title ="Using DelegateCommand" Width ="350" Height ="275" > <StackPanel HorizontalAlignment ="Center" VerticalAlignment ="Center" > <CheckBox IsChecked ="{Binding IsEnabled}" Content ="Can Execute Command" Margin ="10" /> <Button Command ="{Binding ExecuteDelegateCommand}" Content ="DelegateCommand" Margin ="10" /> <Button Command ="{Binding DelegateCommandObservesProperty}" Content ="DelegateCommand ObservesProperty" Margin ="10" /> <Button Command ="{Binding DelegateCommandObservesCanExecute}" Content ="DelegateCommand ObservesCanExecute" Margin ="10" /> <Button Command ="{Binding ExecuteGenericDelegateCommand}" CommandParameter ="Passed Parameter" Content ="DelegateCommand Generic" Margin ="10" /> <TextBlock Text ="{Binding UpdateText}" Margin ="10" FontSize ="22" /> </StackPanel > </Window >
MainWindowViewModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 using System;using Prism.Commands;using Prism.Mvvm;namespace UsingDelegateCommands.ViewModels { public class MainWindowViewModel : BindableBase { private bool _isEnabled; public bool IsEnabled { get { return _isEnabled; } set { SetProperty(ref _isEnabled, value ); ExecuteDelegateCommand.RaiseCanExecuteChanged(); } } private string _updateText; public string UpdateText { get { return _updateText; } set { SetProperty(ref _updateText, value ); } } public DelegateCommand ExecuteDelegateCommand { get ; private set ; } public DelegateCommand<string > ExecuteGenericDelegateCommand { get ; private set ; } public DelegateCommand DelegateCommandObservesProperty { get ; private set ; } public DelegateCommand DelegateCommandObservesCanExecute { get ; private set ; } public MainWindowViewModel () { ExecuteDelegateCommand = new DelegateCommand(Execute, CanExecute); DelegateCommandObservesProperty = new DelegateCommand(Execute, CanExecute) .ObservesProperty(() => IsEnabled); DelegateCommandObservesCanExecute = new DelegateCommand(Execute) .ObservesCanExecute(() => IsEnabled); ExecuteGenericDelegateCommand = new DelegateCommand<string >(ExecuteGeneric) .ObservesCanExecute(() => IsEnabled); } private void Execute () { UpdateText = $"Updated: {DateTime.Now} " ; } private void ExecuteGeneric (string parameter ) { UpdateText = parameter; } private bool CanExecute () { return IsEnabled; } } }
View部分:
头部引入命名空间,指定ViewModeLocator模式:
1 2 xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True"
接着是一个:
1 <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"></StackPanel>
接着内部是一组控件,一个CheckBox四个Button一个 TextBlock。
1 CheckBox IsChecked="{Binding IsEnabled}"
复选框的勾选状态绑定到一个布尔型属性上。
1 Button Command="{Binding ExecuteDelegateCommand}"
普通命令绑定
1 Button Command="{Binding ExecuteGenericDelegateCommand}" CommandParameter="Passed Parameter"
带参数的 命令绑定
1 TextBlock Text="{Binding UpdateText}"
为TextBlock的Text属性绑定数据源
Binding语法 Property=”{Binding PropertyPath}”,PropertyPath就是VM
当为Command进行Binding的时候,还可以带参数,使用CommandParameter属性,上面的CommandParameter指定了一个字符串“Passed Parameter”,当然还可以为其Binding一个对象。
ViewModel部分:
set方法中的:
SetProperty(ref _isEnabled, value); 属性变更的通知,当视图状态更新后,会通知VM更改_isEnabled。
ExecuteDelegateCommand.RaiseCanExecuteChanged(); 这段代码,则会通知ExecuteDelegateCommand的可执行状态更改了,让他重新获取下可执行状态,那他是怎么获取可执行状态的呢?我们看下这个Command:
ExecuteDelegateCommand = new DelegateCommand(Execute, CanExecute); new 的时候,有两个参数,第一个是Action(无返回类型的方法)Execute(需要执行的方法),第二个是一个Func,就是一个返回布尔型的方法CanExecute来获取command的可执行状态,当上面通知他可执行状态变更后,他就会重新调用CanExecute方法来获取目前的可执行状态(也就是按钮的可按下状态),来看下这个方法:
1 2 3 4 private bool CanExecute (){ return IsEnabled; }
很简单,直接返回了IsEnabled,而他是跟视图的CheckBox的IsChecked绑定的,当然也可以返回_isEnabled,而我更倾向后面这个,Public那个是给外人用的,蛤蛤。
当然可执行状态,还有其他的更优雅的写法,也就不用写ExecuteDelegateCommand.RaiseCanExecuteChanged();了,具体代码如下:
1 2 3 4 DelegateCommandObservesProperty = new DelegateCommand(Execute, CanExecute) .ObservesProperty(() => IsEnabled); DelegateCommandObservesCanExecute = new DelegateCommand(Execute) .ObservesCanExecute(() => IsEnabled);
下面这个是带参数的命令(command),他的回调函数需要一个string类型的参数,在new的时候要指定入参类型:
1 2 ExecuteGenericDelegateCommand = new DelegateCommand<string >(ExecuteGeneric) .ObservesCanExecute(() => IsEnabled);
回调函数ExecuteGeneric:
1 2 3 4 private void ExecuteGeneric (string parameter ){ UpdateText = parameter; }