lte__ lte__ - 2 years ago 141
C# Question

C# with WPF - Keyboard not binding?

I want to enable, disable and re-enable certain keyboard strokes in my WPF program based on certain conditions. I have the binding currently like this:

<KeyBinding Command="{Binding UpCommand}" Key="Up"/>
<KeyBinding Command="{Binding DownCommand}" Key="Down"/>
<KeyBinding Command="{Binding LeftCommand}" Key="Left"/>
<KeyBinding Command="{Binding RightCommand}" Key="Right"/>

And then in the ViewModel:

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

Now, this works as supposed, except that the key binding is enabled all the time while the program is running. The gamefield doesn't disappear after a game is finished, but I don't want the user to be able to move (~use the keys) until she/he starts a new game via
. And that's why I'd like to move the
binding to
instead of the constructor (and unbind it in
). However, if I do move the instantiation of the new DelegateCommands to
, the key binding doesn't happen and I'm unable to play.
works as expected, but the keyboard binding doesn't (it does work, however, when it's in the constructor).

How can I make sure the key binding is enabled after
until a game is finished, but is disabled after
is run again? Why is placing the
new DelegateCommand
s to
not working? Thank you!


I have IPropertyChanged implemented as follows:

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));

However, even if I'm trying

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

it doesn't work. What am I missing?

Answer Source

Your commands are still bound properties, just with a special type ICommand. That means that it works the same as any other binding. If you want elements to pick up a change to a bound property they need to raise PropertyChanged. Because your commands are using auto-properties, that event isn't raised.

The reason you don't normally have to do this is property assignments in a constructor happen before the bindings evaluate.

As for "removing" the bindings; you could set them to null (and raise PropertyChanged as appropriate) but a better solution would be to use a DelegateCommand (or a custom command object) that supports CanExecute/CanExecuteChanged and use that to "disable" the commands when the program isn't in a valid state.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download