2016-11-22 13 views
1

特定の条件に基づいてWPFプログラムで特定のキーボードストロークを有効、無効、再有効にしたいとします。私はこのように、現在結合している:ViewModelにでC#with WPF - キーボードはバインドされていませんか?

//MainWindow.xaml 
... 
<Window.InputBindings> 
    <KeyBinding Command="{Binding UpCommand}" Key="Up"/> 
    <KeyBinding Command="{Binding DownCommand}" Key="Down"/> 
    <KeyBinding Command="{Binding LeftCommand}" Key="Left"/> 
    <KeyBinding Command="{Binding RightCommand}" Key="Right"/> 
</Window.InputBindings> 
... 

そして:さて、これはプログラムの実行中にキーバインドをすべての時間を有効になっていることを除いて、仮定として

//MLViewModel.cs 
class MLViewModel : ViewModelBase 
{ 
    public DelegateCommand UpCommand { get; private set; } 
    public DelegateCommand DownCommand { get; private set; } 
    public DelegateCommand LeftCommand { get; private set; } 
    public DelegateCommand RightCommand { get; private set; } 

    public MLViewModel(MLModel model) 
    { 
    ... 
     Lvl1Command = new DelegateCommand(param => { SetUpGame(MLModel.Level.Easy); }); 
     Lvl2Command = new DelegateCommand(param => { SetUpGame(MLModel.Level.Medium); }); 
     Lvl3Command = new DelegateCommand(param => { SetUpGame(MLModel.Level.Hard); }); 

     UpCommand = new DelegateCommand(param => { _model.MoveUp(); RefreshTable(); }); 
     DownCommand = new DelegateCommand(param => { _model.MoveDown(); RefreshTable();}); 
     LeftCommand = new DelegateCommand(param => { _model.MoveLeft(); RefreshTable(); }); 
     RightCommand = new DelegateCommand(param => { _model.MoveRight(); RefreshTable(); });  
    } 

    private void SetUpGame(MLModel.Level level) 
    { 
    // setting up the field etc. 
    } 

    private void Model_GameOver(object sender, MLEventArgs e) 
    { 
    // handling the event of the game being over 
    } 
} 

の作品。ゲームが終了してもゲームフィールドは消えませんが、ユーザーはSetUpGame()で新しいゲームを開始するまで、ユーザーがキーを移動することはできません。それで、私は[Up-Down-Left-Right]Commandバインディングをコンストラクタの代わりにSetUpGame()に移動したいと思います(そして、それをModel_Gameoverでアンバインドします)。しかし、私が新しいDelegateCommandsのインスタンス化をSetUpGame()に移すと、キーバインディングが発生せず、再生できません。 Lvl[1-2-3]Commandは期待通りに機能しますが、キーボードバインディングはありません(ただし、コンストラクタ内にある場合は機能します)。

SetUpGameの後にキーバインドが有効になっていることを確認して、Model_GameOverからSetUpGameを再度実行するまで無効にするにはどうすればよいですか? new DelegateCommandSetUpGame()に割り当てているのはなぜですか?ありがとうございました!

ADDITION

次のように私が実装しているIPropertyChanged:

namespace SavageMaci.ViewModel 
{ 
    public abstract class ViewModelBase : INotifyPropertyChanged 
    { 
     protected ViewModelBase() { } 

     public event PropertyChangedEventHandler PropertyChanged; 

     protected virtual void OnPropertyChanged([CallerMemberName] String propertyName = null) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 
} 

をしかし、私はそれが動作しません

DownCommand = new DelegateCommand(param => { _model.MoveDown(); RefreshTable(); OnPropertyChanged(); }); 

をしようとしている場合でも。私は何が欠けていますか?

答えて

0

コマンドは依然として特殊なタイプのICommandでバインドされたプロパティです。つまり、他のバインディングと同じと同じ意味です。バインドされたプロパティの変更を要素が受け取るようにするには、PropertyChangedを呼び出す必要があります。コマンドが自動プロパティを使用しているため、そのイベントは発生しません。

は通常である必要があります。これは、バインディングが評価される前にコンストラクタ内のプロパティ代入が行われるためです。

バインディングを「削除」する場合は、それらをヌルに設定して(適切な場合はPropertyChangedを上げることもできます)、より良い解決策は、CanExecute/CanExecuteChangedをサポートするDelegateCommand(またはカスタムコマンドオブジェクト)を使用して、それがプログラムを有効な状態。

+0

申し訳ありませんが、私は自分自身の問題を正確に記述していませんでした。レベルコマンドはうまく動作しますが、キーストロークコマンドはうまく動作しません。私は既に実装していた質問に 'IPropertyChanged'の実装を追加しました。 –

+0

明示的に 'OnPropertyChange(" UpCommand ")'などを追加するとうまくいきます。 –

+0

バインディングの削除に関して、私は 'DownCommand.CanExecute(false);'を試みていて、その後 'OnPropertyChanged(" DownCommand " ); 'しかし、これはバインディングを無効にしません。何か不足していますか? –

関連する問題