WPF:对于 ICommand 的一些理解
前言
在使用 ICommand 之前,我们先了解一下这个接口。
ICommand
public interface ICommand
{
    /// <summary>
    /// 用于通知使用者,当前命令的可执行条件发生变化。需要使用者主动调用 CanExecute 判定是否可执行命令。
    /// </summary>
    event EventHandler CanExecuteChanged;
    
    /// <summary>
    /// 用于判定是否可执行命令
    /// </summary>
    /// <param name="parameter">命令参数</param>
    /// <returns></returns>
    bool CanExecute(object parameter);
    
    /// <summary>
    /// 执行命令
    /// </summary>
    /// <param name="parameter">命令参数</param>
    void Execute(object parameter);
}在笔者看来,ICommand 就是对函数的一种封装。只是在调用这个函数前,必须进行一个可执行判定。
比如,在假期中使用滴滴打车。
执行参数:打车距离
执行函数:将乘客送到目的地。
可执行条件:打车距离必须大于5公里,才会有司机接单。
上述看法,只是单独从接口本来而言。
WPF 中为什么要定义 ICommand ?
在 WPF 中定义这样一个接口的目的是为了实现 MVVM 的框架设计,换一种的说法就是为了解耦。
代码演示
常规
视图
<Window x:Class="Demo.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="{Binding Title}" Height="350" Width="525">
    <Grid>
        <Button Content="关闭窗口" Click="ButtonBase_OnClick"/>
    </Grid>
</Window>后台代码
using System.Windows;
namespace Demo.Views
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            Close();
        }
    }
}MVVM 模式
视图
<Window x:Class="Demo.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="{Binding Title}" Height="350" Width="525">
    <Grid>
        <Button 
            CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
            Command="{Binding Path=CloseWindowCommand}"
            Content="关闭窗口"/>
    </Grid>
</Window>prism:ViewModelLocator.AutoWireViewMode = "true"
等价于
new MainWindow().DataContext = new MainWindowViewModel()
视图模型
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
using Prism.Commands;
using Prism.Mvvm;
namespace Demo.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private string _title = "Prism Application";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }
        public ICommand CloseWindowCommand { get; }
        public MainWindowViewModel()
        {
            CloseWindowCommand = new DelegateCommand<DependencyObject>(CloseWindowCommandExecuteMethod);
        }
        private void CloseWindowCommandExecuteMethod(DependencyObject obj)
        {
            var window = Window.GetWindow(obj);
            window?.Close();
        }
    }
}
如果,单独从上面2种演示来看。好像没看出来 MVVM 和常规模式有什么区别。
那么,现在加入一种变化。
新增一个窗口 Window1,它也需要实现关闭窗口的命令。
常规模式的做法是,Window1 后台代码中再实现一次函数调用。
MVVM 模式的做法是 new Window1().DataContext = new MainWindowViewModel()。
说明常规模式下,视图和功能函数耦合在一起,无法做到复用。
而 MVVM 模式下,视图和功能函数是分开。
在 WPF 中 ICommand 可以在视图元素的事件触发后,执行调用。
如果,把视图元素和 ICommand 比作是甲方和乙方的话。
视图元素:甲方,功能函数的调用方
ICommand:乙方,功能函数的实际执行者
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号