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:
//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>
...
And then in the ViewModel:
//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
}
}
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 SetUpGame()
. And that's why I'd like to move the [Up-Down-Left-Right]Command
binding to SetUpGame()
instead of the constructor (and unbind it in Model_Gameover
). However, if I do move the instantiation of the new DelegateCommands to SetUpGame()
, the key binding doesn't happen and I'm unable to play. Lvl[1-2-3]Command
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 SetUpGame
until a game is finished, but is disabled after Model_GameOver
until SetUpGame
is run again? Why is placing the new DelegateCommand
s to SetUpGame()
not working? Thank you!
ADDITION
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?
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.