WPF: Команда на холсте не работает

#c# #wpf #mvvm

#c# #wpf #mvvm

Вопрос:

Я внедряю простую Tetris игру MVVM . Основная панель есть Canvas . Я хочу перемещаться с помощью стрелок клавиатуры. Для этого я реализовал MoveLeftCommand и MoveRightCommand . Команды привязаны к ViewModel внутренней KeyBinding части.

Ниже моя xaml реализация

 <Canvas
    Width="{Binding Width}"
    Height="{Binding Height}"
    >
    <Canvas.InputBindings>
        <!-- One type of implementation -->
        <KeyBinding Key="{Binding MoveLeftCommand.GestureKey}"
                    Command="{Binding MoveRightCommand}"/>
        <!-- Different style of implementation -->
        <KeyBinding Key="{Binding MoveLeftCommand.GestureKey}"
                    Command="{Binding MoveLeftCommand}"/>
    </Canvas.InputBindings>
    ...
</Canvas>
  

Команды инициализируются в конструкторе ViewModel «s».

 public RelayCommand MoveRightCommand { get; set; }
public RelayCommand MoveLeftCommand { get; set; }

public GamePanelViewModel()
{
    this.MoveLeftCommand = new RelayCommand(new Action(MoveLeft));
    this.MoveLeftCommand.GestureKey = Key.Left;
    this.MoveRightCommand = new RelayCommand(new Action(MoveRight));
    this.MoveRightCommand.GestureKey = Key.Right;
}
  

И вот реализация команды:

 public class RelayCommand : ICommand
{
    private Action action;
    public Key GestureKey { get; set; }

    public RelayCommand(Action action) { this.action = action; }

    public bool CanExecute(object parameter) { return true; }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter) { this.action(); }
}        
  

Soultion не работает.

В режиме отладки, когда я нажимаю клавишу со стрелкой влево или вправо, выполнение даже не входит CanExecute в метод. Он ведет себя так, как если бы он не знал о командах.

Я также пытался принудительно сфокусироваться на Canvas . Результата нет. Еще одна вещь, которую я пробовал, это реализовать команды по-другому. Результата тоже нет.

Однако, когда я добавил простой Textbox поверх Canvas , и реализовал те же команды на Textbox , он начал работать — я мог перемещаться по игре с помощью стрелок.

Есть идеи, почему команды Canvas были проигнорированы?

Спасибо

Комментарии:

1. Это потому Canvas , что не имеет фокуса клавиатуры. WPF начинается с сфокусированного элемента управления и поднимается вверх по визуальному дереву, чтобы увидеть, есть ли команда, которая обрабатывает этот жест. Например, включите Button ваш Canvas и сфокусируйте его, тогда он должен работать или делать что-то вроде <Canvas ... x:Name="myCanvas" Focusable="True"> и на Window.Loaded событии делать myCanvas.Focus();

2. Спасибо, настройка фокуса работает отлично. Я пытался заставить его раньше, но без настройки Focusable = True . Что касается первого решения, я понял трюк с другим элементом управления, но на мой вкус это было слишком сложно.

Ответ №1:

Я думаю, что ваша проблема возникает из-за простой проблемы инициализации.

Причина, по которой ничего не работает, заключается в том, что привязка произошла до создания объекта RoutedCommand .

замените свойства вашей команды следующей реализацией :

     private RelayCommand moveRightCommand;
    public RelayCommand MoveRightCommand
    {
        get
        {
            if (moveRightCommand == null)
            {
                moveRightCommand = new RelayCommand(MoveRight);
                moveRightCommand.GestureKey = Key.Right;
            }
            return moveRightCommand;
        }
    }
  

В качестве альтернативы вы можете создать их так, как вы это делаете, и вызвать событие PropertyChanged в свойстве команды.

     private RelayCommand moveRightCommand;
    public RelayCommand MoveRightCommand
    {
        get
        {               
            return moveRightCommand;
        }
        set
        {
            moveRightCommand = value;
            PropertyChanged(this, new PropertyChangedEventArgs("MoveRightCommand"));
        }
    }
  

Комментарии:

1. Команды создаются в конструкторе до того, как возвращается указатель на GamePanelViewModel , поэтому он должен работать и будет работать, если Canvas или что-то в нем будет иметь фокус клавиатуры.

2. Я попробовал оба ваших предложения. К сожалению, ни то, ни другое не сработало.