最近我有机会玩Windows 8 Release Preview(Build 8400具体)。我的目的是调查只在Windows 8下出现在我们的产品(WPF应用程序)中的错误。这些错误看起来非常简单 - 几个按钮在不应该被禁用时被禁用。看起来容易修复,但我决定找到根本原因。
事实证明,当绑定到命令的控件收到CanExecuteChanged
通知时,如果发送方不是相同的命令,则它不会重新查询命令的CanExecute
方法。在命令对模型执行某些操作并且它的执行能力取决于模型的状态时,这是一个问题。例如,假设您有一个模型:
class MyModel
{
public void ChangeModel(bool makeValidForCommand)
{
Valid = makeValidForCommand;
if (ModelChanged != null)
ModelChanged(this, new EventArgs());
}
public bool Valid { get; private set; }
public event EventHandler ModelChanged;
}
一个命令:
class MyCommand : ICommand
{
public MyCommand(MyModel model)
{
_model = model;
}
public bool CanExecute(object parameter)
{
return _model.Valid;
}
public event EventHandler CanExecuteChanged
{
add { _model.ModelChanged += value; }
remove { _model.ModelChanged -= value; }
}
public void Execute(object parameter) { }
private MyModel _model;
}
不幸的是,这在Windows 8上不起作用 - 在模型更改状态后,绑定到命令的按钮将保持不正确地禁用(或启用)。它在Windows 7上运行得非常好!
命令可以这样重写:
class MyCommand : ICommand
{
public MyCommand(MyModel model)
{
_model = model;
}
public bool CanExecute(object parameter)
{
return _model.Valid;
}
public event EventHandler CanExecuteChanged
{
add
{
_canExecuteChanged += value;
_model.ModelChanged -= _modelChanged;
_model.ModelChanged += _modelChanged;
}
remove
{
_canExecuteChanged -= value;
_model.ModelChanged -= _modelChanged;
}
}
public void Execute(object parameter)
{
}
private void _modelChanged(object sender, EventArgs e)
{
if (_canExecuteChanged != null)
_canExecuteChanged(this, new EventArgs());
}
private event EventHandler _canExecuteChanged;
private MyModel _model;
}
现在发送者就是命令本身,一切都很好。另一种选择是使用CommandManager
及其RequerySuggested
事件:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
又一次有效!嗯,现在我完全不解了。发件人不是命令 - 它是空的,但是如果我尝试使用null发送者发送我自己的事件,它将不再起作用。
有没有人面对同样的事情?在新Windows上这是一种奇怪的优化方式吗?老实说,它看起来更像是一个错误。
答案 0 :(得分:4)
似乎,这是.Net Framework 4.5的一个重大变化。 这个问题在这里报告给微软: