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:乙方,功能函数的实际执行者

posted @   2324736194  阅读(2084)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示