最近、Windows 8 Release Preview (具体的にはビルド 8400) を少し試す機会がありました。私の目的は、私たちの製品 (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; }
}
そして再びそれは機能します!うーん、今、私は完全に困惑しています。Sender はコマンドではありません - null ですが、null の送信者で自分のイベントを送信しようとすると、再び機能しません。
誰かが同じに直面しましたか?新しい Windows での最適化の奇妙な方法ですか? 正直なところ、それはバグのように見えます。