带WPF的C# - 键盘不绑定?

时间:2016-11-22 21:15:08

标签: c# wpf xaml

我想根据特定条件在我的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>
...

然后在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
    }
}

现在,除了在程序运行时始终启用键绑定外,它的工作原理如此。游戏完成后游戏场不会消失,但我不希望用户能够移动(〜使用键),直到他/他通过SetUpGame()开始新游戏。这就是为什么我想将[Up-Down-Left-Right]Command绑定移动到SetUpGame()而不是构造函数(并在Model_Gameover中取消绑定)。但是,如果我确实将新的DelegateCommands的实例化移动到SetUpGame(),则不会发生键绑定,我无法播放。 Lvl[1-2-3]Command按预期工作,但键盘绑定没有(它确实有效,但是,当它在构造函数中时)。

如何确保在SetUpGame之后启用键绑定,直到游戏结束,但在Model_GameOver之后被禁用,直到再次运行SetUpGame为止?为什么将new DelegateCommand置于SetUpGame()不起作用?谢谢!

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

它不起作用。我错过了什么?

1 个答案:

答案 0 :(得分:0)

您的命令仍然是绑定属性,只有特殊类型ICommand。这意味着它的工作与任何其他绑定相同。如果您希望元素获取对绑定属性的更改,则需要引发PropertyChanged。因为您的命令使用自动属性,所以不会引发该事件。

通常必须这样做的原因是构造函数中的属性赋值在绑定评估之前发生。

至于“删除”绑定;您可以将它们设置为null(并根据需要引发PropertyChanged),但更好的解决方案是使用支持DelegateCommand的{​​{1}}(或自定义命令对象)并将其用于“禁用“程序未处于有效状态时的命令。