2010-05-20 33 views
5

Tôi đang cố gắng xây dựng một trò chơi mẫu trong Silverlight 4 bằng cách sử dụng mẫu thiết kế MVVM để mở rộng kiến ​​thức của tôi. Tôi đang sử dụng bộ công cụ MvvmLight của Laurent Bugnion (tìm thấy ở đây: http://mvvmlight.codeplex.com/). Tất cả những gì tôi muốn làm ngay bây giờ là di chuyển một hình dạng xung quanh trong Canvas bằng cách nhấn các phím cụ thể. Giải pháp của tôi chứa một Player.xaml (chỉ là một hình chữ nhật; điều này sẽ được di chuyển xung quanh) và MainPage.xaml (Canvas và một thể hiện của điều khiển Player).Silverlight 4 + MVVM + Sự kiện KeyDown

Theo hiểu biết của tôi, Silverlight không hỗ trợ các sự kiện định tuyến đường hầm, chỉ tạo bọt. Vấn đề lớn của tôi là Player.xaml không bao giờ nhận ra sự kiện KeyDown. Nó luôn luôn bị chặn bởi MainPage.xaml đầu tiên và nó không bao giờ đạt đến bất kỳ điều khiển con nào vì nó bong bóng lên trên. Tôi muốn rằng logic để di chuyển Player nằm trong lớp PlayerViewModel, nhưng tôi không nghĩ rằng Player có thể biết về bất kỳ sự kiện KeyDown nào bắn mà không có tôi chuyển chúng một cách rõ ràng từ MainPage.

Tôi đã kết thúc việc thêm logic xử lý vào lớp MainPageViewModel. Bây giờ vấn đề của tôi là MainPageViewModel không có kiến ​​thức về Player.xaml nên nó không thể di chuyển đối tượng này khi xử lý các sự kiện KeyDown. Tôi đoán điều này là dự kiến, vì ViewModels không nên có bất kỳ kiến ​​thức về quan điểm liên quan của họ.

Trong không quá nhiều từ ... có cách nào mà người chơi này điều khiển người dùng trong MainPage.xaml của tôi có thể trực tiếp chấp nhận và xử lý các sự kiện KeyDown không? Nếu không, phương pháp lý tưởng cho MainPageViewModel của tôi là giao tiếp với điều khiển con của View là gì? Tôi đang cố gắng để giữ mã ra khỏi các tập tin mã phía sau càng nhiều càng tốt. Có vẻ như tốt nhất là đặt logic vào ViewModels để dễ kiểm tra và tách giao diện người dùng khỏi logic.

(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 
     } 
} 

Cảm ơn trước, Jeremy

+0

MainViewModel của bạn có quyền truy cập vào đối tượng trình phát của bạn không? Nếu vậy, không thể đối tượng Player có một phương thức trên nó được gọi là MoveUp(), sau đó trong sự kiện KeyPressed bạn chỉ có thể gọi Player.MoveUp()? Bằng cách này, logic cho việc di chuyển của Player sẽ vẫn ở trong đối tượng Player. – JSprang

+0

Không, nó không có tham chiếu đến đối tượng Trình phát. Nó không liên quan đến XAML, đó là cách tôi nghĩ MVVM được cho là hoạt động. Có cách nào tôi có thể ràng buộc trường hợp XAML của tôi Player với một biến trong MainViewModel? – jturinetti

Trả lời

3

Thay vì sử dụng EventTrigger, cố gắng sử dụng KeyTrigger và đặt đối tượng Source thành LayoutRoot.

Một tùy chọn khác (mà tôi nghĩ là tốt hơn) là để cho ViewModel xử lý vị trí của trình phát. Ví dụ, có một thuộc tính được gọi là PlayerTop và một thuộc tính có tên là PlayerLeft. Liên kết thuộc tính Canvas.Top và Canvas.Left của Player với các thuộc tính này. Khi người dùng nhấn phím, một lệnh được thực thi trên máy ảo để cập nhật các thuộc tính này. Bằng cách này, VM không phải biết những gì được di chuyển, hoặc nó được di chuyển như thế nào.

Điều đó có hợp lý không?

+0

Cảm ơn! Tôi đã kết thúc bằng cách sử dụng gợi ý thứ hai của bạn. Tôi đã có một vấn đề nữa mặc dù ... bởi vì Player có DataContext của nó ràng buộc với PlayerViewModel của nó trong XAML của nó ở cấp UserControl, các liên kết Canvas.Top và Canvas.Left của Player trong MainPage.xaml không thể tìm thấy thuộc tính PlayerTop/PlayerLeft . Tôi đã phải di chuyển liên kết DataContext của Player xuống đến điều khiển root Grid của nó. – jturinetti

Các vấn đề liên quan