Я пытаюсь построить пример игры в 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
}
}
Заранее спасибо,
Джереми