1

假设我正在实现一个 Winforms UI,其中所有命令都遵循以下模式:

interface ICommand
{
    bool CanExecute { get; }
    void Execute();
}

触发此类命令的按钮或菜单项应具有以下设置:

  • 属性Enabled绑定到命令的CanExecute
  • 事件Click链接到命令的Execute(由于方法签名不同,通过中间事件处理程序)

麻烦的CanExecute是,INotifyPropertyChanged在这里实现它不会起作用,因为这个属性不能直接修改,而是取决于程序中的其他因素,不需要与命令相关。并且不必PropertyChanged在程序的完全不相关的部分中触发命令事件。

您如何让数据绑定管理器知道何时CanExecute更改?

这是我的问题的一个(纯属虚构)示例:

bool CanExecute
{
    get
    {
        return User.LoggedInForAtLeastNMinutes(5);
        // how would you trigger data-binding updates for CanExecute? 
    }
}

理想情况下,我希望 UI 不断检查CanExecute(好像它是一个易失性字段),但 AFAIK 这不是 Winforms 数据绑定的工作方式。有没有人有这个问题的解决方案?


注意:我知道 WPF,顺便说一句。我的问题的背景是,我将在 WPF 的大方向上逐步改进现有的 Winforms 应用程序。但实际上使用 WPF 并因此摆脱我所问的问题现在是不可行的。

4

3 回答 3

2

不管怎样,我都会实施INotifyPropertyChanged(或添加一个CanExecuteChanged具有相同效果的事件)。我会努力让对象知道何时在正确的时间引发属性更改事件,而不是轮询。

例如,在您的虚构示例中,您可能有一个UserLoggedIn事件。对此,您可以设置一个 5 分钟的计时器;当该计时器过去时,您会引发属性更改事件。

如果您采用投票方式,那么您将面临两个危险:

  • 轮询过于频繁,您的应用程序会消耗 CPU 检查尚不可能发生的事件(例如,每 10 秒轮询一次以查看 5 分钟是否结束)
  • 轮询不够频繁,绑定到CanExecute属性的控件滞后于 UI 的其余部分(例如,进行文本选择和CopyTextCommand.CanExecute属性更新之间的延迟)

一种混合方法是C++中的 Microsoft 基础类采用的方法,即在应用程序的消息循环空闲时进行此检查。当您知道只有用户界面交互会影响您的CanExecute属性时,这是一种合理的方法。

于 2010-08-01T10:10:49.597 回答
1

使用 aTimer不断地轮询CanExecute属性。PropertyChanged属性更改时引发事件。

于 2010-08-01T09:44:33.340 回答
0

我对 Application.Idle 事件进行轮询,只要您可以执行的逻辑简单,应该没有任何问题。

这是我当前的“CommandManager”实现的摘录;

 public CommandManager()
    {
        Commands = new List<ICommand>();

        Binders = new List<ICommandBinder>
                      {
                          new ControlBinder(),
                          new MenuItemCommandBinder()
                      };

        Application.Idle += UpdateCommandState;
    }
 private void UpdateCommandState(object sender, EventArgs e)
    {
        Commands.Do(c => c.Enabled);
    }

(Do() 只是一个执行 foreach 的扩展方法,如 linq Select() 但采取 Action 而不是 Func)

我前段时间写过关于这个的博客,请随时查看:http ://codewithpassion.blogspot.com/2010/11/icommand-and-commandmanager-for-windows.html

希望能帮助到你

于 2010-12-01T21:01:51.417 回答