Silverlight 4 + MVVM + событие KeyDown - PullRequest
5 голосов
/ 20 мая 2010

Я пытаюсь построить пример игры в Silverlight 4, используя шаблон проектирования MVVM, чтобы расширить свои знания. Я также использую инструментарий Лорана Бюньона MvvmLight (находится здесь: http://mvvmlight.codeplex.com/). Все, что я хочу сейчас сделать, - это перемещать фигуры внутри холста, нажимая определенные клавиши. Мое решение содержит Player.xaml (просто прямоугольник; он будет перемещен) и MainPage.xaml (Canvas и экземпляр элемента управления Player).

Насколько я понимаю, Silverlight не поддерживает туннелирование маршрутизируемых событий, только пузырьки. Моя большая проблема в том, что Player.xaml никогда не распознает событие KeyDown. Сначала он всегда перехватывается MainPage.xaml и никогда не достигает дочерних элементов управления, потому что он всплывает вверх. Я бы предпочел, чтобы логика перемещения Player была в классе PlayerViewModel, но я не думаю, что Player может знать о любых событиях KeyDown, которые запускаются без явной передачи их из MainPage.

Я закончил тем, что добавил логику обработчика в класс MainPageViewModel. Теперь моя проблема в том, что MainPageViewModel ничего не знает о Player.xaml, поэтому он не может переместить этот объект при обработке событий KeyDown. Я предполагаю, что это ожидаемо, поскольку ViewModels не должен иметь никаких знаний об их связанных представлениях.

Не так много слов ... есть ли способ, которым пользовательский элемент управления Player в моем MainPage.xaml может напрямую принимать и обрабатывать события KeyDown? Если нет, то каков идеальный метод для моего MainPageViewModel для взаимодействия с дочерними элементами управления его представления? Я стараюсь как можно больше хранить код в файлах с выделенным кодом. Похоже, для простоты тестирования лучше всего поместить логику во ViewModels и отделить пользовательский интерфейс от логики.

(MainPage.xaml)

<UserControl x:Class="MvvmSampleGame.MainPage"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:game="clr-namespace:MvvmSampleGame"             
         xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
         xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL4"
         mc:Ignorable="d"
         Height="300"
         Width="300"
         DataContext="{Binding Main, Source={StaticResource Locator}}">

<i:Interaction.Triggers>
    <i:EventTrigger EventName="KeyDown">
        <cmd:EventToCommand Command="{Binding KeyPressCommand}" PassEventArgsToCommand="True" />
    </i:EventTrigger>
</i:Interaction.Triggers>

<Canvas x:Name="LayoutRoot">       
    <game:Player x:Name="Player1"></game:Player> 
</Canvas>

(MainViewModel.cs)

public MainViewModel()
{

  KeyPressCommand = new RelayCommand<KeyEventArgs>(KeyPressed);

}       

public RelayCommand<KeyEventArgs> KeyPressCommand
{
    get;
    private set;
}

private void KeyPressed(KeyEventArgs e)
{

        if (e.Key == Key.Up || e.Key == Key.W)
        {
            // move player up

        }
        else if (e.Key == Key.Left || e.Key == Key.A)
        {
            // move player left
        }
        else if (e.Key == Key.Down || e.Key == Key.S)
        {
            // move player down
        }
        else if (e.Key == Key.Right || e.Key == Key.D)
        {
            // move player right
        }
}

Заранее спасибо, Джереми

1 Ответ

3 голосов
/ 21 мая 2010

Вместо использования EventTrigger, попробуйте использовать KeyTrigger и установить для объекта Source значение LayoutRoot.

Другой вариант (который я считаю лучше) - позволить ViewModel управлять позицией игрока. Например, есть свойство с именем PlayerTop и свойство с именем PlayerLeft. Привязать к ним свойства игрока Canvas.Top и Canvas.Left. Когда пользователь нажимает клавиши, на виртуальной машине выполняется команда, которая обновляет эти свойства. Таким образом, виртуальная машина не должна знать, что перемещается или как она перемещается.

Имеет ли это смысл?

...