Sto provando a creare un gioco di esempio in Silverlight 4 utilizzando il modello di progettazione MVVM per ampliare le mie conoscenze. Uso anche il toolkit MvvmLight di Laurent Bugnion (disponibile qui: http://mvvmlight.codeplex.com/). Tutto quello che voglio fare adesso è spostare una forma all'interno di una tela premendo tasti specifici. La mia soluzione contiene un Player.xaml (solo un rettangolo che verrà spostato) e MainPage.xaml (il Canvas e un'istanza del controllo Player).Silverlight 4 + MVVM + KeyDown evento
Per la mia comprensione, Silverlight non supporta tunneling eventi indirizzati, solo spumeggiante. Il mio grosso problema è che Player.xaml non riconosce mai l'evento KeyDown. Viene sempre prima intercettato da MainPage.xaml e non raggiunge mai alcun controllo figlio perché bolle verso l'alto. Preferirei che la logica per spostare il Player sia nella classe PlayerViewModel, ma non penso che il Player possa sapere di eventuali eventi KeyDown che si attivano senza che io li faccia esplicitamente passare da MainPage.
ho finito di aggiungere la logica gestore alla classe MainPageViewModel. Ora il mio problema è che il MainPageViewModel non ha alcuna conoscenza di Player.xaml, quindi non può spostare questo oggetto quando gestisce eventi KeyDown. Immagino che questo è previsto, in quanto ViewModels non dovrebbe avere alcuna conoscenza delle loro viste associate.
In non così tante parole ... c'è un modo in cui questo controllo utente Player nel mio MainPage.xaml può accettare e gestire gli eventi KeyDown direttamente? In caso contrario, qual è il metodo ideale per il mio MainPageViewModel per comunicare con i controlli figlio di View? Sto cercando di mantenere il codice dei file code-behind il più possibile. Sembra che sia meglio mettere la logica in ViewModels per facilità di test e per disaccoppiare l'interfaccia utente dalla logica.
(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
}
}
Grazie in anticipo, Jeremy
Il tuo MainViewModel ha accesso al tuo oggetto giocatore? In tal caso, non è possibile che l'oggetto Player abbia un metodo chiamato MoveUp(), quindi nell'evento KeyPressed è possibile chiamare Player.MoveUp()? In questo modo, la logica per lo spostamento del Player sarebbe ancora nell'oggetto Player. – JSprang
No, non ha un riferimento all'oggetto Player. Non ha alcun riferimento allo XAML, ed è così che pensavo che MVVM avrebbe dovuto funzionare. C'è un modo per legare la mia istanza XAML del Player a una variabile in MainViewModel? – jturinetti