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

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

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

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



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

本文内容

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

一个最简单的例子

<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/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。


walter lv

博客专家

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

私信
关注

原文地址:https://www.cnblogs.com/lonelyxmas/p/12051997.html

时间: 2024-08-05 12:58:29

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

【webpack】-- 自动刷新

前端需要频繁的修改js和样式,且需要根据浏览器的页面效果不断的做调整:而且往往我们的开发目录和本地发布目录不是同一个,修改之后需要发布一下:另外一点就是并不是所有的效果都可以直接双击页面就能看到,我们常常需要在本地用nginx建一个站点来观察(自己电脑上ok了才放到测试环境去).所以如果要用手工刷新浏览器和手动(或点击)发布,还要启动站点,确实是个不小的体力活.而这三点webpack可以帮我们做到. webpack-dev-server webpack是通过webpack-dev-server(

jekyll+livereload+chrome插件-更新文件后自动刷新

2014-08-27 本文不保证成功,window系统会出现各种问题,如若不成功,请直接用livereload的window版,解决,详细可以查看livereload下载对应版本操作,比较傻瓜式: 以下主要介绍的是命令行配置的方式: jekyll+livereload更新后自动刷新,老外的教程,先看看: http://dan.doezema.com/2014/01/setting-up-livereload-with-jekyll/ 1.安装guard-jekyll-plus 时会出错,依赖包版

gulp+browserSync自动刷新页面

BrowserSync "Browsersync能让浏览器实时.快速响应您的文件更改(html.js.css.sass.less等)并自动刷新页面.更重要的是 Browsersync可以同时在PC.平板.手机等设备下进项调试.您可以想象一下:"假设您的桌子上有pc.ipad.iphone.android等设备,同时打开了您需要调试的页面,当您使用browsersync后,您的任何一次代码保存,以上的设备都会同时显示您的改动".无论您是前端还是后端工程师,使用它将提高您30%的

Chrome 实现前端页面自动刷新

作为一个前端,主要是写页面,但是每次写完一段代码,保存,如果想看看刚刚写的代码的效果怎样,还需要到浏览器手动刷新,刷新,刷新,刷的手疼了. 所以如果能实现只要在编辑器中保存,浏览器自动刷新页面,那岂不是很棒嘛!!So convenient~~ 所以本文介绍如何实现浏览器自动刷新. 1.需要安装: livereload,Chrome 安装这个扩展程序 然后,window 用户需要还需要下载安装个客户端, http://livereload.com/ 最后,使用 npm 全局安装 http-serv

使用node-livereload自动刷新页面

1. 安装node 2. 安装python 3. 安装connect, serve-static和node-livereload (以下都假设命令行当前目录为e:\WebSite) e:\WebSite>npm install connect e:\WebSite>npm install serve-static e:\WebSite>npm install livereload 如果出现类似:MSB8036: The Windows SDK version 8.1 was not fo

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

---恢复内容开始--- 请想象这样一个场面:你开着两个显示器,一边是IDE里的代码,另一边是浏览器里的你正在开发的应用.此时桌上还放着你的手机,手机里也是这个开发中的应用.然后,你新写了一小段代码,按下了ctrl+s保存.紧接着,你的手机和另一个显示器里的应用,就变成了更新后的效果.你可以马上检查效果是否和你预想的一致,甚至都不需要动一下鼠标... 想起来还不错?嗯,这只是简单地省略掉那个开发过程中会按好多遍的F5刷新. 自动刷新 “自动刷新”并不是新的概念,但对关注“可见”的预览效果的前端开

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

学习过程宝宝心里苦,不能怨政府.. 兴趣所致,一直放不下nodejs的学习,时隔多日,又把express捡起来打算重新再学学,一直没什么太大的长进,和实际的项目经验.真的醉了,太懒了. 今天在重新研究supervisor的时候,突然觉得这东西只有在服务端文件修改时才会触发刷新,前端样式文件模板等等刷新时不会, 能实现前端修改也自动刷新不?想想平时自己用gulp 搭虚拟服务器,用browser自动刷新,于是打算试试. gulp+browserSync 算是原来就有的,现在应该把目标分几步来实现,

前端开发 ---浏览器自动刷新

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Helvetica; color: #000000 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Helvetica; color: #000000; min-height: 13.0px } span.s1 { } span.Apple-tab-span { white-space: pre } 1.livereload (1

Emacs中自动刷新dired缓冲区

Emacs中自动刷新dired缓冲区 在dired模式中,如果在不同buffer间切换,buffer不会自动更新,有时还需要手工按“g”键,比较麻烦,如下设置和代码能够在buffer切换和执行shell命令后自动更新dired buffer: ;; 切换buffer后,立即刷新 (defadvice switch-to-buffer (after revert-buffer-now activate) (if (eq major-mode 'dired-mode) (revert-buffer)