当前位置: 首页 > news >正文

WPF 的命令的自动刷新时机——当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因

在 WPF 中,你可以使用 Command="{Binding WalterlvCommand}" 的方式来让 XAML 中的一个按钮或其他控件绑定一个命令。这样,按钮的可用性会自动根据 WalterlvCommand 当前 CanExecute 的状态来改变。这本是一个非常智能的特性,直到你可能发现你按钮的可用性状态不正确……

本文介绍默认情况下,WPF 在 UI 上的这些命令会在什么时机进行刷新;以及没有及时刷新时,可以如何强制让这些命令的可用性状态进行刷新。了解了这些,你可能能够解决你在 WPF 程序中命令绑定的一些坑。


This post is written in multiple languages. Please select yours:

  • WPF 的命令的自动刷新时机——当你 CanExecute 会返回 true 但命令依旧不可用时可能是这些原因 - walterlv
  • When WPF Commands update their CanExecute states? - walterlv

本文内容

    • 一个最简单的例子
    • 如何手动刷新命令
    • WPF 的命令在何时刷新?

一个最简单的例子

<Button x:Name="TestCommand" Command="{Binding WalterlvCommand}" />
public class Walterlv
{
    // 省略了此命令的初始化。
    public WalterlvCommand WalterlvCommand { get; }
}

public class WalterlvCommand : ICommand
{
    public bool SomeFlag { get; set; }

    bool ICommand.CanExecute(object parameter)
    {
        // 判断命令的可用性。
        return SomeFlag;
    }

    void ICommand.Execute(object parameter)
    {
        // 省略了执行命令的代码。
    }
}

假如 SomeFlag 一开始是 false,5 秒种后变为 true,那么你会注意到这时的按钮状态并不会刷新。

var walterlv = new Walterlv();
TestCommand.DataContext = walterlv;

await Task.Delay(5000);
walterlv.WalterlvCommand.SomeFlag = true;

当然,以上所有代码会更像伪代码,如果你不熟悉 WPF,是一定编译不过的。我只是在表达这个意思。

如何手动刷新命令

调用以下代码,即可让 WPF 中的命令刷新其可用性:

CommandManager.InvalidateRequerySuggested();

WPF 的命令在何时刷新?

默认情况下,WPF 的命令只会在以下时机刷新可用性:

  • KeyUp
  • MouseUp
  • GotKeyboardFocus
  • LostKeyboardFocus

使用通俗的话来说,就是:

  • 键盘按下的按键抬起的时候
  • 在鼠标的左键或者右键松开的时候
  • 在任何一个控件获得键盘焦点或者失去键盘焦点的时候

这部分的代码可以在这里查看:

  • CommandDevice.PostProcessInput

最关键的代码贴在这里:

// 省略前面。
if (e.StagingItem.Input.RoutedEvent == Keyboard.KeyUpEvent ||
    e.StagingItem.Input.RoutedEvent == Mouse.MouseUpEvent ||
    e.StagingItem.Input.RoutedEvent == Keyboard.GotKeyboardFocusEvent ||
    e.StagingItem.Input.RoutedEvent == Keyboard.LostKeyboardFocusEvent)
{
    CommandManager.InvalidateRequerySuggested();
}

然而,并不是只在这些时机进行刷新,还有其他的时机,比如这些:

  • Menu 菜单的子菜单项打开的时候(参见 MenuItem.OnIsSubmenuOpenChanged)
  • 在长按滚动条中的按钮以连续滚动的过程中(参见 Tracker.DecreaseRepeatButton)
  • DataGridCell 的只读属性改变的时候(参见 DataGridCell.OnNotifyIsReadOnlyChanged)
  • DataGrid 中的各种各样的操作中(参见 DataGrid)
  • JournalNavigationScope 向后导航的时候(参见 JournalNavigationScope.OnBackForwardStateChange)
  • 还有其他,你可以在此链接双击 InvalidateRequerySuggested 查看:InvalidateRequerySuggested

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • 将 C++/WinRT 中的线程切换体验带到 C# 中来(WPF 版本)
  • 如何在 MSBuild 的项目文件 csproj 中获取绝对路径
  • C# 跨设备前后端开发探索
  • MSBuild 如何编写带条件的属性、集合和任务 Condition?
  • WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码
  • 如何快速自定义 Visual Studio 中部分功能的快捷键
  • C# 8.0 如何在项目中开启可空引用类型的支持
  • C# 8.0 可空引用类型中的各项警告/错误的含义和示例代码
  • C# 可空引用类型 NullableReferenceTypes 更强制的约束:将警告改为错误 WarningsAsErrors
  • ClearType 的原理:Windows 上文本的亚像素控制
  • 使用 7-Zip 的命令行版本来压缩和解压文件
  • 在项目文件 csproj 中或者 MSBuild 的 Target 中使用 % 引用集合中每一项的属性
  • MSBuild 中的特殊字符($ @ % 等):含义、用法以及转义
  • WPF 获取元素(Visual)相对于屏幕设备的缩放比例,可用于清晰显示图片
  • Visual Studio 通过修改项目的调试配置文件做到临时调试的时候不要编译(解决大项目编译缓慢问题)
  • “大数据应用场景”之隔壁老王(连载四)
  • 【刷算法】求1+2+3+...+n
  • bearychat的java client
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • Linux后台研发超实用命令总结
  • PAT A1120
  • Python十分钟制作属于你自己的个性logo
  • Redis的resp协议
  • 和 || 运算
  • 后端_ThinkPHP5
  • 离散点最小(凸)包围边界查找
  • 容器服务kubernetes弹性伸缩高级用法
  • 如何编写一个可升级的智能合约
  • 入门到放弃node系列之Hello Word篇
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 优秀架构师必须掌握的架构思维
  • 走向全栈之MongoDB的使用
  • 最近的计划
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • linux 淘宝开源监控工具tsar
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • 容器镜像
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • !!Dom4j 学习笔记
  • # Maven错误Error executing Maven
  • # 数据结构
  • #QT(一种朴素的计算器实现方法)
  • (1)bark-ml
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • .Net调用Java编写的WebServices返回值为Null的解决方法(SoapUI工具测试有返回值)
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • .so文件(linux系统)
  • /etc/apt/sources.list 和 /etc/apt/sources.list.d
  • @WebService和@WebMethod注解的用法
  • [ vulhub漏洞复现篇 ] struts2远程代码执行漏洞 S2-005 (CVE-2010-1870)