14

私はWindows8用のC#とXAMLを使用して最初のゲームの作成に取り組んでいます。コアの概念とベストプラクティスをまだ学んでおり、MVVMはハードルでした。私は2つの部分で質問をしようとします。

バックグラウンド

私が作っているゲームは数独です。数独には、9x9グリッドのタイルを含むボードがあります。、、、の3つのモデルがGameありBoardますTile。aGameが作成されると、自動的にが作成され、が作成さBoardれると、Board81(9x9)が作成されますTiles

1.ビューの階層を使用して、対応するビューモデルはどのように作成されますか?

モデルの階層を一致させるために、ビューの階層(81を含むを含むGameView)が必要です。XAMLでは、ユーザーコントロールを使用してこのビューの階層を作成するのは非常に簡単ですが、ビューモデルがどのように作成されるのかわかりません。BoardViewTileViews

私が見た例では、ユーザーコントロールのデータコンテキストは、ビューモデルViewModelLocatorの新しいインスタンスを作成するビューモデル(ソースとして使用)に設定されることがよくあります。これは、フラットビューの場合はうまく機能するようですが、階層がある場合は厄介になるようにも見えます。を作成し、それを子に任せてGameView作成しますか?もしそうなら、どのように通信しますか?通信は階層をバックアップすることができますか?GameViewModelBoardViewBoardViewModelGameViewModelBoardViewModelBoardViewModelGameViewModel

2.ビューモデルはどのようにモデルデータを取得しますか?

GameiOSでは、サービスを使用して、データが事前に入力されたモデルをフェッチすることから始めます。次に、GameViewControllerビューコントローラ(ビューの作成を担当)を作成し、Gameそれに渡します。MVVMでは、ビューが独自のビューモデルの作成を担当することの価値はわかりますが(理想的にはを使用してViewModelLocator)、そのビューモデルがモデルを取得する方法がわかりません。

私がオンラインで見つけたすべての例で、ビューモデルは独自のデータをフェッチするために何らかのサービスを使用しています。しかし、コンストラクターパラメーターまたはより高いレベルのナビゲーションから渡されたパラメーターを受け入れる例はありません。これはどのように行われますか?

モデルにアプリケーションリソースやその他の種類のシングルトンストレージメソッドを使用したくないのは、使用しないためですが、画面に複数のパズルを一度に表示したい場合はどうすればよいですか?それぞれGameViewに独自のが含まれている必要がありますGame

モデルGameViewModelへの参照が必要なだけでなく、何らかの方法で作成されたモデル(質問1を参照)には、モデルに属するモデルへの参照が必要です。同じことがすべてに当てはまります。このすべての情報はどのようにチェーンに渡されますか?完全にXAML内でこれほど手間のかかる作業を行うことはできますか、それともコードで何らかのバインディングやその他の初期化を行う必要がありますか?GameBoardViewModelBoardGameTiles

ふぅ!

完全な答えではない場合でも、アドバイスをいただければ幸いです。また、自分と同じような課題を共有するMVVMプロジェクトの例を見つけたいと思っています。トンありがとう!

4

1 に答える 1

19

まず、アプリケーションを開始するためのクラスを作成します。通常、私はそのクラスをまたはのようなものと呼びますがApplicationViewModelShellViewModel技術的には、私が通常使用するものとは異なるルールに従うことができます。ViewModel

このクラスは起動時にインスタンス化されDataContextShellViewまたはApplicationView

// App.xaml.cs
private void OnStartup(object sender, StartupEventArgs e)
{
    var shellVM = new ShellViewModel(); 
    var shellView = new ShellView();    
    shellView.DataContext = shellVM;  
    shellView.Show(); 
}

これは通常、DataContextUIコンポーネントに直接設定する唯一の場所です。この時点から、ViewModelsはアプリケーションになります。MVVMを使用する場合は、このことを覚えておくことが重要です。ビューは、ユーザーがViewModelを操作できるようにするユーザーフレンドリーなインターフェイスです。これらは実際にはアプリケーションコードの一部とは見なされません。

たとえば、次のものShellViewModelが含まれている場合があります。

  • BoardViewModel CurrentBoard
  • UserViewModel CurrentUser
  • ICommand NewGameCommand
  • ICommand ExitCommand

そしてあなたShellViewはこのようなものを含むかもしれません:

<DockPanel>
    <Button Command="{Binding NewGameCommand}" 
            Content="New Game" DockPanel.Dock="Top" />
    <ContentControl Content="{Binding CurrentBoard}" />
</DockPanel>

これにより、実際にはBoardViewModelオブジェクトがとしてUIにレンダリングされますContentControl.Content。の描画方法を指定するには、を指定するBoardViewModelか、暗黙的にを使用します。DataTemplateContentControl.ContentTemplateDataTemplates

暗黙のDataTemplateは、関連付けられてDataTemplateいないクラス用です。x:KeyWPFは、UIで指定されたクラスのオブジェクトに遭遇するたびに、このテンプレートを使用します。

だから使用する

<Window.Resources>
    <DataTemplate DataType="{x:Type local:BoardViewModel}">
        <local:BoardView />
    </DataTemplate>
</Window.Resources>

描く代わりに

<ContentControl>
    BoardViewModel
</ContentControl>

描画します

<ContentControl>
    <local:BoardView />
</ContentControl>

今、は次のBoardViewようなものを含むことができます

<ItemsControl ItemsSource="{Binding Squares}">
    <ItemsControl.ItemTemplate>
        <ItemsPanelTemplate>
            <UniformGrid Rows="3" Columns="3" />
        </ItemsPanelTemplate>
    <ItemsControl.ItemTemplate>
</ItemsControl>

そして、3x3を使用してボードを描画し、UniformGrid各セルにはSquares配列の内容が含まれます。BoardViewModel.Squaresプロパティがオブジェクトの配列である場合TileModel、各グリッドセルにはが含まれTileModel、暗黙的に使用して、DataTemplateそれぞれの描画方法をWPFに指示できます。TileModel

ViewModel実際のデータオブジェクトを取得する方法については、それはあなた次第です。私は、などのクラスの背後にあるすべてのデータアクセスを抽象化しRepositoryViewModel単に。のようなものを呼び出すことを好みますSodokuRepository.GetSavedGame(gameId);。これにより、アプリケーションのテストと保守が容易になります。

ただし、データを取得する場合は、ViewModelModelsがアプリケーションであることに注意してください。したがって、データの取得はユーザーが担当する必要があります。でそれをしないでくださいViewModel個人的には、データのみを保持するプレーンオブジェクトのレイヤーを保持するのが好きなので、ViewModelからのみデータアクセス操作を実行します。

間のコミュニケーションについてはViewModels、実際にブログにそのことについての記事があります。EventAggregator要約すると、MicrosoftPrismやMVVMLightなどのメッセージングシステムを使用しますMessenger。これらは一種のページングシステムのように機能します。どのクラスも特定のタイプのメッセージを受信するようにサブスクライブでき、どのクラスもメッセージをブロードキャストできます。

たとえば、メッセージを受信するShellViewModelようにサブスクライブし、メッセージを受信したときにアプリケーションを閉じたり、アプリケーションのどこからでもメッセージをExitProgramブロードキャストしたりできます。ExitProgram

CurrentBoardViewModel.ExitCommand += Exit;別の方法は、からの呼び出しなど、あるクラスから別のクラスにハンドラーをアタッチすることShellViewModelだと思いますが、それは面倒で、メッセージングシステムを使用することを好みます。

とにかく、私はあなたの質問のいくつかに答えて、あなたを正しい方向に向けることを願っています。あなたのプロジェクトで頑張ってください:)

于 2012-09-07T16:54:59.620 に答える