2012-08-15 63 views
4

最近我有机会玩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上进行优化是否是一种奇怪的方式?老实说,它看起来更像是一个错误。

+1

这是奇怪... WPF是在.NET框架中实现,而不是在Windows中,所以它不应该不管你正在使用的Windows版本。您在Windows 8上使用了哪个版本的.NET? – 2012-08-15 15:09:57

+0

确实,但我认为框架中存在与系统相关的部分,在Win7和Win8上显然不同。我构建了我的4.0版应用程序。 – Maxym 2012-08-15 15:40:08

+0

令人惊讶的是,我将目标框架版本从4.0更改为3.5,该错误消失了。 – Maxym 2012-08-15 15:43:21

回答

4

似乎,这是.Net Framework 4.5中的重大变化。 问题报告给微软在这里:

http://connect.microsoft.com/VisualStudio/feedback/details/751429/wpf-icommand-canexecutechanged-behaviour-change-in-net-4-5

+0

这也打击了我,花了相当长的时间,直到我终于弄清楚为什么我的应用程序不能在安装了.net 4.5的系统上工作。经过大量的调试和搜索后,我发现这让我可以修复它。我正在使用使用null作为发件人的RelayCommand。 – 2012-11-23 09:43:25