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

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

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


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

一个最简单的例子

<Button x:Name="TestCommand" Command="{Binding WalterlvCommand}" />
  • 1
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)
{
// 省略了执行命令的代码。
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

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

var walterlv = new Walterlv();
TestCommand.DataContext = walterlv; await Task.Delay(5000);
walterlv.WalterlvCommand.SomeFlag = true;
  • 1
  • 2
  • 3
  • 4
  • 5

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

如何手动刷新命令

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

CommandManager.InvalidateRequerySuggested();
  • 1

WPF 的命令在何时刷新?

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

  • KeyUp
  • MouseUp
  • GotKeyboardFocus
  • LostKeyboardFocus

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

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

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

最关键的代码贴在这里:

// 省略前面。
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();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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


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

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

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

发布了382 篇原创文章 · 获赞 232 · 访问量 47万+

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

  1. 浏览器自动刷新——基于Nodejs的Gulp LiveReload与VisualStudio完美结合。

    本文版权桂博客园和作者吴双共同所有,转载和爬虫请注明原文地址 http://www.cnblogs.com/tdws/p/6016055.html 写在前面 大家好我是博客园的蜗牛,博客园的蜗牛就是我 ...

  2. Sublime3和Chrome配置自动刷新网页【实测可用】

    SublimeText2下的LiveReload在SublimeText3下无法正常使用,本文整理SublimeText3安装LiveReload的方法.win7下实测可用! 安装成功后,就不需要再手 ...

  3. gulp之压缩合并MD5清空替换加前缀以及自动编译自动刷新浏览器大全

    gulp是基于流的前端构件化工具.目前比较火的前端构建化工具还是挺多的,grunt gulp fis3等等. 这个鬼东西有什么用?请参考https://www.zhihu.com/question/3 ...

  4. SQL实现类似于自动刷新数据的功能

    有时需要在SQL中,定时刷新某张表,比如说是要定时查询某张表的行数,通常做法就是手动的按F5去执行来刷新数据.但是如果这个定时查询历时较长,10分钟,或半小时,手动的话肯定是要崩溃了.貌似SQL没有像 ...

  5. Windows Phone 8 LongListSelector实现下拉自动刷新列表

    LongListSelector是一个加强版的列表控件,它可以实现分组的列表,如系统人脉列表的交互效果就可以利用LongListSelector控件去实现,同时LongListSelector也一样可 ...

  6. gulp自动刷新插件

    gulp自动刷新的插件很多,但是感觉最好用的还是 browser-sync 插件.如果不想用命令行,也可以使用 browser-sync界面工具 先安装 browser-sync 插件: npm in ...

  7. BrowserSync,调试利器--自动刷新(转

    ---恢复内容开始--- 请想象这样一个场面:你开着两个显示器,一边是IDE里的代码,另一边是浏览器里的你正在开发的应用.此时桌上还放着你的手机,手机里也是这个开发中的应用.然后,你新写了一小段代码, ...

  8. gulp+browserSync+nodemon 实现express 全端自动刷新的实践

    学习过程宝宝心里苦,不能怨政府.. 兴趣所致,一直放不下nodejs的学习,时隔多日,又把express捡起来打算重新再学学,一直没什么太大的长进,和实际的项目经验.真的醉了,太懒了. 今天在重新研究 ...

  9. gulp最佳实践(包含js,css,html预编译,合并,压缩,浏览器自动刷新)

    gulp是基于流的自动化构建工具官方网址:http://www.gulpjs.com.cn/ 一.安装需要的模块 1.新建package.json,输入下面的内容 { "name" ...

随机推荐

  1. 小程序使用npm安装第三方包

    安装vant 小程序UI库 进到小程序目录,在地址栏中cmd 进入DOS界面  npm init -f  安装vant 小程序UI库 npm i vant-weapp -S --production ...

  2. 让ie10/11支持非单页面的vue/es6

    为了满足某些客户的要求,最近让前端同学实现了ie 10(windows 7)/11(windows 10)支持多页面的vue/es6,基本参考如下: https://www.cnblogs.com/n ...

  3. Laravel 控制器 Controller

    一.控制器存在的意义 路由可以分发请求:路由中还可以引入 html 页面:我们可以在 route/web.php 中搞定一切了:但是如果把业务逻辑都写入到路由中:那路由将庞大的难以维护:于是控制器就有 ...

  4. 运维笔记--Docker环境ubuntu系统安装指定版本python[3.6]

    场景描述: 直接安装出现如下异常: root@ae2d02e458f3:/home# apt-get install python3.6 Reading package lists... Done B ...

  5. angular自定义module

    在app.module.ts里面,imports部分,添加你的自定义模块名在你的自定义模块内,添加了component以后,需要添加exports导出,类似下面 import { NgModule } ...

  6. 小程序 图表 antv f2 的使用

    官方组件版 https://github.com/antvis/wx-f2/tree/custom-components 官方npm版 https://github.com/antvis/wx-f2 ...

  7. Mybatis出错: Cause: org.apache.ibatis.reflection.ReflectionException: Error instantiating class com.cyf.pojo.User with invalid types () or values ()

    org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: org.apache.ib ...

  8. 锐捷交换机如何配置远程管理地址(telnet)

    基本命令如下: hostname(config)#username admin password 123456  ------>telnet 登录账号为admin密码为123456 hostna ...

  9. echo的色彩处理

    在Shell脚本中,可以使用echo的-e选项使显示内容呈现出不同的颜色. 格式1:echo -e "\033[背景颜色代码;文字颜色代码m 输出的字符串 \033[0m" 格式2 ...

  10. Clojure 哲学

    简单性.专心编程不受打扰(freedom to focus).给力(empowerment).一致性和明确性:Closure编程语言中几乎每一个元素的设计思想都是为了促成这些目标的实现. 学习一门新的 ...