最近我有机会玩Windows 8发布预览(Build 8400具体)。我的目标是仅在Windows 8下调查出现在我们的产品(WPF应用程序)中的错误。这些错误看起来非常简单 - 几个按钮在不应该时被禁用。它看起来很容易修复,但我决定找到根本原因。Windows 8上的命令绑定问题(发布预览版)
事实证明,当绑定到命令的控件收到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上进行优化是否是一种奇怪的方式?老实说,它看起来更像是一个错误。
这是奇怪... WPF是在.NET框架中实现,而不是在Windows中,所以它不应该不管你正在使用的Windows版本。您在Windows 8上使用了哪个版本的.NET? – 2012-08-15 15:09:57
确实,但我认为框架中存在与系统相关的部分,在Win7和Win8上显然不同。我构建了我的4.0版应用程序。 – Maxym 2012-08-15 15:40:08
令人惊讶的是,我将目标框架版本从4.0更改为3.5,该错误消失了。 – Maxym 2012-08-15 15:43:21