Published: 06 Jan 2010
By: Xianzhong Zhu
Download Sample Code

In this second part, we will continue to discuss the WaspKiller game development—to extend the functionalities with the server-side database support. As mentioned in the first part, we’re going to rest upon another well-known design pattern, MVVM, to achieve the extension, and at the same time, introduce Microsoft .NET RIA Services framework to smooth out the whole architecture design.

Contents [hide]

The WaspKiller Game with Silverlight 3, .NET RIA Services, MVP and MVVM Patterns Series

  • Part 1 In this article, we will focus upon the development of the front end of the game using the MVP pattern; in the second part, we will discuss the database related work using the MVVM pattern.
  • Part 2 In this second part, we will continue to discuss the WaspKiller game development - to extend the functionalities with the server-side database support. As mentioned in the first part, we're going to rest upon another well- known design pattern, MVVM, to achieve the extension, and at the same time, introduce Microsoft .NET RIA Services framework to smooth out the whole architecture design.
  • Introduction to MVVM

    The Model View ViewModel ("MVVM" in short) is an architectural pattern used in software engineering that originated from Microsoft as a specialization of the PresentationModel design pattern specific for the Windows Presentation Foundation (WPF). Largely based on the Model-view-controller pattern (MVC), MVVM was designed to make use of specific functions in WPF to better facilitate the separation of View layer development from the rest of the pattern by removing virtually all "code behind" from the View layer. Instead of requiring interactive designers to write view code, they can use the native WPF markup language XAML and create bindings to the ViewModel, which is written and maintained by application developers. This separation of roles allows interactive designers to focus on UX needs rather than programming or business logic, allowing for the layers of an application to be developed in multiple work streams.

    Apparently, the Model-View-ViewModel pattern attempts to gain both the advantages of separation of functional development provided by MVC as well as leveraging the advantages of XAML and the Windows Presentation Foundation by binding data as far back as possible while using the XAML, ViewModel, and any Business Layer's inherent data checking features to validate any incoming data. The result is that the Model drives as much of the operations as possible, minimizing the need for "code behind," especially in the View.

    Figure 1 below gives a rough description of the MVVM schema.

    Figure 1: The general architecture of the MVVM pattern

    The 

general architecture of the MVVM pattern

    The list below further enumerates the respective functionalities of Model, View, and ViewModel.

    • Model: as in the classic MVC pattern, the model refers to the data access layer representing the real state content.
    • View: as in the classic MVC pattern, the view refers to all elements displayed by the GUI such as buttons, windows, graphics, and other controls.
    • ViewModel: the ViewModel is a "Model of the View", which means it is an abstraction of the View that also serves in data binding between the View and the Model. It could be seen as a specialized aspect of what would be a Controller (in the MVC pattern) that acts as a data binder/converter that changes Model information into View information and passes commands from the View into the Model. The ViewModel exposes public properties, commands, and abstractions. The ViewModel has been likened to a conceptual state of the data as opposed to the real state of the data in the Model.

    The key thing to remember is that you have one and only one ViewModel per view. The view model communicates with the model (business logic, services whatever below it). The view does not need to know about any else in your architecture. Another major point is that you do not any code behind your view and the data-binding deals with the communication to the view model and what ever the view model exposes.

    Why .NET RIA Services

    Recently, Microsoft .NET RIA Services framework has become a hot topic, especially as far as Visual Studio 2010 Beta is concerned.

    To further simplify Line of Business (LoB) RIA development and address the complexity of building N-tier applications, Microsoft Silverlight creates a strong foundation framework, .NET RIA Services, which aims to complement the existing Data Access Layer and presentation components in the .NET framework and Silverlight.

    For more details about .NET RIA Services, you can refer to other related documents provided by Microsoft and tons of blogs. Herein, I merely want to explain why I chose .NET RIA Services framework. In fact, all the things are clear: a real scenario online game is often large, with complex data persisted on the server side. In our case, the user score related data just need to be stored on the server-side SQL Server database. Further, these data are nearly independent of the other components in the front end of the game. All these cases are just suitable to be managed with .NET RIA Services framework. Of course, as a simple and dummy Silverlight game, introducing .NET RIA Services framework seems to put a big fish in a small pound. Then again, all I aim to is to learn the new frameworks.

    To gain a clearer understanding with the game application, let's preview the folders and files related architecture in our game system, as shown in Figure 2 below.

    Figure 2: The general .NET RIA Services based architecture of the game application

    The general .NET RIA Services based architecture of the game application

    Next, let's follow the .NET RIA Services pointed ideas to construct the server side stuffs first.

    Preparing the Server-side Modules

    To create a more practical Silverlight game, I introduce a backend SQL Server 2008 database named WaspGameDB with which to hold the player related score data. For simplicity, we construct only one table named HighScore. The following table indicates all the fields and related notes.

    Table 1: The definition of table HighScore

    Field name

    Type

    Notes

    ID

    int

    Identifying the record and incremental, no nullable.

    Player

    nvarchar(50)

    The player name, no nullable.

    Score

    int

    the high score of the player, no nullable.

    GameLevel

    int

    Identifying the skill of the player, no nullable.

    PubDate

    datetime

    The date time to submit the score related data, no nullable.

    Using the Entity Framework to Set Up the Entity Models

    In this example, our mid-tier (in .NET RIA Services words, the server side) will use data from a database. In the .NET RIA Services design, the client tier will be unaware of the data access technology or schema used by the mid-tier.

    To use a database on our mid-tier, we may access the WaspGameDB database using the Entity Framework (it's a recommendable solution, isn't it?). To do this, we start by using Add New Item on the server project and in the subsequent dialog select the ADO.NET Entity Data Model template, as shown in Figure 3 below.

    Figure 3: Select the ADO.NET Entity Data Model template

    Select the ADO.NET Entity Data Model template

    Creating a DomainService on the Mid-tier

    Now we come to the critical step that demonstrates the features of the .NET RIA Services framework; creating a DomainService on the mid-tier. A DomainService is a class that exposes entities and operations for a specific data domain. It is also where the developer adds application logic.

    The .NET RIA Services framework itself contains the plumbing code to make the entities and operations declared in a DomainService class available to other tiers.

    We will create our sample DomainService by selecting the server project and choosing Add New Item. Under the Web category is the new Domain Service Class template, as indicated in Figure 4. We name this new DomainService class HighScoreService.

    Figure 4: Add a new Domain Service class

    Add a new Domain 

Service class

    Subsequently, this template will invoke a wizard to help construct the DomainService class. In this case we'll select the WaspGameDB model we just created, and expose only one entity, HighScore. We will tick the "Enable editing" checkbox, which means the HighScore entity will be read and written. Figure 5 shows the last dialog in the wizard.

    Figure 5: Customize the client access dialog

    Customize the 

client access dialog

    After we commit this dialog, the new DomainService class HighScoreService will be created in the selected project.

    For brevity, we are not going to list the auto-generated code. However, we must bear in mind that the HighScoreService class takes the responsibility of providing the public interface to the mid-tier data. The code generated by the wizard is just a starting point, and we will add our own application logic herein.

    Thanks to .NET RIA Services framework, we can now run our application without any modifications, and the HighScore entity will be available on both the mid-tier and the client tier.

    Note

    To access the .NET RIA Services related stuffs created on the server side from the front end, we have to build the solution; or else, when you click "Show All Files" in the client project, none of the server-side related targets will appear.

    Since now everything is ready on the server side, let's shift our attention to the front end design. However, this time, rather than use the MVP pattern we are going to use another pattern, i.e. MVVM, to extend the front end. As hinted above, let's next explore each module one by one.

    Designing the Model Interface and Custom Event Argument Classes

    To facilitate the communication between the model and the view model, it's advisable to set up an interface first to access the data layer. On the other hand, by constructing the interface, it also becomes more convenient for later possible unit testing. The model interface in this game is called IHighScoreData, shown in the listing below.

    Listing 1: Code to define the model interface

    As is shown, the IHighScoreData interface contains methods to retrieve and save data. Taking into account the typical asynchronous communication feature of Silverlight framework, we've declared the two methods with non-actual data returned. Instead they will fire corresponding events for success and failure.

    And also, you've seen that there are three custom event arguments defined above. This is to enable notification of the results to the caller of our interface. Now, we also list the related definitions of the three custom event argument classes below:

    Listing 2: Code to define the custom event argument class

    Examining carefully, you will find out that the class HighScoreLoadingEventArgs exposes the important entity type HighScore as an enumerable list of entities that contains the results the caller requested, as you will see in later code. The second class HighScoreSavingEventArgs is used to pass data when the player wants to save data to the server side. So, you can pay attention to the usage of the public property CurrentScore later on. The final class HighScoreErrorEventArgs is apparently used for data loading or saving exception manipulation.

    Designing the Model

    Now, we can start to create the model class HighScoreData that implements the above IHighScoreData interface. The following gives the complete definition for this class.

    Listing 3: The complete definition for the model class HighScoreData

    Experienced readers may quickly find out that the HighScoreData class simply wraps the ADO.NET Data Service so that when a request for retrieving or saving data comes in, it executes the associated request and throws a corresponding event.

    Another point worth taking notice of is the private property Context, which is of type HighScoreContext. As one of the important types provided by the server side via .NET RIA Services framework, HighScoreContext derives from DomainContext to define a couple of extension methods to cope with our interested entities.

    The third point should be noticed is the implementation of the method SaveChanges. After we pass an entity HighScore to it, it will invoke the line of code Context.HighScores.Add(en as HighScore ) to modify the target collection HighScores on the client side. After that, it will execute the next line of code to submit the changes to the server side. Inside the callback function OnSubmitCompleted, we just invoke the event method (i.e. fire the related event) HighScoreSavingComplete with an instance of the custom event class HighScoreSavingEventArgs as the second argument. All these, you see, result from the event mechanism of C#.

    Note

    According to Microsoft Silverlight infrastructure, the user interface can only be updated from a main or UI thread. And if you readers are familiar with the event mechanism in RAD languages (Visual Basic for example) and comprehend this will bring numerous advantages in decoupling the application modules, you will know better the design we introduced above.

    Let's next dig into the view model related design.

    Designing the View Model

    According to the MVVM pattern, the view model should try to expose data that is directly needed by the view. Therefore, we have to make clear what the view really needs. However, in real scenarios, we are always creating the view model and the view in parallel, re-factoring the view model if the view brings forward new requirements.

    The following listing shows the definition of the view model.

    Listing 4: The view model class HighScoresViewModel

    Here, you should pay special attention to the handlers relating to the four events HighScoreLoadingComplete, HighScoreSavingComplete, HighScoreLoadingError, and HighScoreSavingError. These handlers receive events from the model and then fire events to the view. The really interesting thing is that the model passes to the view model the list of retrieved results, but instead of passing the results directly to the underlying view, the view model stores the results in their own bindable list (ObservableCollection<HighScore>).

    This above behavior occurs as supposed because the view model is bound directly to the view, so the results will be rendered in the view via the data binding. On the other hand, since the view model takes the reins of the user interface, it can insure the events that it fires happen on the UI thread (generally via Dispatcher.BeginInvoke).

    Let's next look at the MVVM pattern related views design.

    Designing the Views

    In this WaspKiller application, we refer to two views, i.e. ScoreBoard.xaml and GameOverDlg.xaml, as the views in the MVVM pattern.

    The Score Board View

    Let's first take a look at the first score board related view-- ScoreBoard.xaml. Figure 6 shows one of the running-time snapshots of this score board.

    Figure 6: One of the running-time snapshots of the score board

    One of the running-time snapshots of the score board

    As you can image, we rest upon the ChildWindow control introduced in Siverlight 3 to represent the score board. And also, the design seems rather easy with a DataGrid control simply listing the first 50 players related score data. Even now, you are still recommended to do some research into the related XAML code to help make clear how the data come and go between the views and other related parts.

    The first part of the XAML code should be take notice of is as follows:

    Here, we've created a new instance of the view model in the Resources of the view.

    The next important part of the XAML code is shown in Listing x below:

    Listing 5: Bind the data container to the view model

    Apparently, we've used the data binding technique to achieve the task of binding the outermost data container (a Grid control in this case) to the view model. This implies that the entire XAML file will be data bound based on the view model directly.

    In subsequent XAML code the DataGrid control is bound to the data provided through the instance of the view model.

    Next, let's turn our attention to the crucial code behind, as shown in Listing x below.

    Listing 6: The main behind code of the score board

    As you've seen, in the method ScoreBoard_Loaded we used the first line of code to create an instance of the view model. Next, we invoked the method LoadHighScores of the newly-created instance to load score related data into the client side. Does this seem clear and modularized? All this is thanks to the MVVP pattern.

    The Game over View

    The next and final view relevant to the MVVP pattern is the game over view, i.e. file GameOverDlg.xaml. First of all, as usual, let's take a look at the running-time snapshot of this dialog view, as shown in Figure 7 below.

    Figure 7: The running-time snapshot of the game over view

    The running-time snapshot of the game over view

    Also simple, isn't it? As you have doped out, when the player clicks the OK button, the current score related data will be submitted and persisted to the server-side database. If the user clicks the Cancel button, all the data will be discarded, and then he can replay the game.

    Next, let's examine the important coding. First, you should pay attention to the following XAML code:

    As with the ScoreBoard.xaml view, here again we created a new instance of the view model using the declarative mode.

    Listing 7: The relevant code in implementing the ScoreBoard.xaml view

    The first thing worth noticing is that we defined three local variables, with _score and _level to hold the current score and level data. Note these data are passed by the game over view caller! The third variable viewModel is used to hold the new instance of the view model.

    Next, when the OK button is clicked, the method InsertHighScore is called, with four parameters passed as the values of each field of the entity HighScore, to finally submit the current player related data to the server side.

    Until now, the whole .NET RIA Services and MVVP related story comes to the end.

    Summary

    In this series of articles, I've developed a simple Silverlight game, WaspKiller, using the Microsoft .NET RIA Services framework, as well as leveraging the two patterns MVP and MVVP. As a demo application, the game is sure to have many aspects to enhance or supplement.

    One of the goals of this series is to bear out that .NET RIA Services and MVVM are synergistic, and aren't in conflict. Do you think so? And also, because I'm a rookie to the patterns MVP and MVVP there certainly exist a great deal of imperceptible mistakes. So, I sincerely hope veteran developers can help me out, and I hope the small game helps young Silverlight beginners to get started in thinking how the components in it might be effectively combined.

    The WaspKiller Game with Silverlight 3, .NET RIA Services, MVP and MVVM Patterns Series

  • Part 1 In this article, we will focus upon the development of the front end of the game using the MVP pattern; in the second part, we will discuss the database related work using the MVVM pattern.
  • Part 2 In this second part, we will continue to discuss the WaspKiller game development - to extend the functionalities with the server-side database support. As mentioned in the first part, we're going to rest upon another well- known design pattern, MVVM, to achieve the extension, and at the same time, introduce Microsoft .NET RIA Services framework to smooth out the whole architecture design.
  • <<  Previous Article Continue reading and see our next or previous articles Next Article >>

    About Xianzhong Zhu

    I'm a college teacher and also a freelance developer and writer from WeiFang China, with more than fourteen years of experience in design, and development of various kinds of products and applications on Windows platform. My expertise is in Visual C++/Basic/C#, SQL Server 2000/2005/2008, PHP+MyS...

    This author has published 81 articles on DotNetSlackers. View other articles or the complete profile here.

    Other articles in this category


    Displaying Notification Messages in a Silverlight Dashboard Application
    In this article we will see how we could display a notification message and further a list of notifi...
    Air Space Issue in Web Browser Control in Silverlight
    Air Space issue is a common issue in Web Browser control in Silverlight and WPF. To explain the issu...
    TextBox Row Filter in Telerik's RadGridView in Silverlight
    If you have come across the JQGrid features, you might have seen the filter row available as the fir...
    Widget Refresh Timer in MVVM in Silverlight
    In this article we'll see how to refresh and disable widgets using the Model View View-Model pattern...
    Develop a Flexible 2.5D Scene Editor Targeting Silverlight RPG Games - Part 2
    In this article, I'm going to introduce to you how to construct such a 2.5D RPG game scene editor th...
    Top
     
     
     

    Please login to rate or to leave a comment.