J'essaie de créer un exemple de jeu dans Silverlight 4 en utilisant le modèle de conception MVVM pour élargir mes connaissances. J'utilise également la boîte à outils MvvmLight de Laurent Bugnion (disponible ici: http://mvvmlight.codeplex.com/). Tout ce que je veux faire maintenant est de déplacer une forme autour d'un canevas en appuyant sur des touches spécifiques. Ma solution contient un Player.xaml (juste un rectangle, qui sera déplacé) et MainPage.xaml (le Canvas et une instance du contrôle Player). À ma connaissance, Silverlight ne prend pas en charge les événements routés de tunnellisation, mais uniquement le bouillonnement. Mon gros problème est que Player.xaml ne reconnaît jamais l'événement KeyDown. Il est toujours intercepté par MainPage.xaml en premier et il n'atteint jamais les contrôles enfants car il fait des bulles vers le haut. Je préférerais que la logique pour déplacer le joueur soit dans la classe PlayerViewModel, mais je ne pense pas que le joueur puisse savoir que des événements KeyDown se déclenchent sans que je ne les transmette explicitement à partir de MainPage.Événement Silverlight 4 + MVVM + KeyDown
J'ai fini par ajouter la logique du gestionnaire à la classe MainPageViewModel. Maintenant, mon problème est que le MainPageViewModel n'a aucune connaissance de Player.xaml donc il ne peut pas déplacer cet objet lors de la gestion des événements KeyDown. Je suppose que cela est prévu, car ViewModels ne devrait avoir aucune connaissance de leurs vues associées.
Dans pas tellement de mots ... est-il un moyen que ce contrôle utilisateur Player dans mon MainPage.xaml peut directement accepter et gérer les événements KeyDown? Si non, quelle est la méthode idéale pour que mon MainPageViewModel communique avec les contrôles enfants de View? J'essaie de garder le code des fichiers code-behind autant que possible. On dirait qu'il est préférable de mettre de la logique dans les ViewModels pour faciliter les tests et découpler l'interface utilisateur de la logique.
(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
}
}
Merci à l'avance, Jeremy
Est-ce que votre MainViewModel a accès à votre objet joueur? Si oui, l'objet Player ne peut-il pas avoir une méthode appelée MoveUp(), alors dans l'événement KeyPressed, vous pouvez simplement appeler Player.MoveUp()? De cette façon, la logique du déplacement du joueur serait toujours dans l'objet Player. – JSprang
Non, il ne contient aucune référence à l'objet Player. Il n'a aucune référence au XAML, ce que je pensais que MVVM était censé fonctionner. Est-il possible de lier mon instance XAML du lecteur à une variable dans MainViewModel? – jturinetti