At the keynote for the Silverlight 4 Launch alongside Scott Guthrie I demonstrated image(minute 28 to minute 38) how to build a Silverlight 4 application using WCF RIA Services and the new Visual Studio 2010 tooling.

The application I built is an online book store to rival the big boys … OK, well, maybe not the big boys but you get the idea. As promised I am elaborating on the presentation and breaking down the steps to create the application here.

I included the starter solution and the completed solution for this presentation so you can try this out for yourself or simply run the completed solution if that interests you more. In this post I will go through the steps to create the application so you can try this as well.

image 

Here is the completed application that I will show how to build. You can select a book category and the books for that category will appear in the book list in the middle. You can sort by title or author or you can filter the book list by title or author. If you log into the application (as RIA Services integrates well with ASP.NET authentication) I show how to set up permissions to edit the book information too. OK, so this was a stretch as you really don’t want to allow book information to be edited by buyers, but work with me on this :-)

image

imageWhere Do We Start?

Let’s start by examining what is already in the project. Open the starter project and notice that there are already a Silverlight project and a Web project created. imageThe application starts out with a SQL Server database containing information about the books. This image shows the Entity Framework model that maps to the SQL Server database. We will be talking to the EF model which in turn talks to SQL Server. Of course this model can be a 1-1 model to table mapping or it could be much more complex. Also, this could have been an nHibernate model or a custom model … RIA Services will sit on top of a variety of models.

So the lower tier architecture contains a SQL Server database which stores the book information and an Entity Framework model which maps to that SQL Server database. RIA Services will operate on the Entity Framework model for both retrieving and modifying data using LINQ to Entities in this application.

imageCreate the Domain Service

To create the domain service you then add a new Domain Service Class to the Web project and name it BookClubService.cs.

image 

imageConfigure the Domain Service

When you configure the domain service RIA Services can see all of the entities that the Entity Framework model exposes. You can select which entities you want the domain service to imageexpose and if they should be editable through this dialog. I’m going to select the Book, BookOfDay and Category and enable editing of the Book. This tells RIA Services to generate methods in the domain service class to return the entities and to create methods to save changes to the Book entity.

I will also check the box to “Generate associated classes for metadata”. This creates a BookClubService.metadata.cs class. This is where you can define validation and business rules that you want to share between the server and the client. The code in this class will be copied to the Silverlight client when the application is compiled.

 </f ont>

imageReturning Object Graphs

When we get the book of the day we want to get the BookOfDay entity and its child entity, Book. By default when asking for a BookOfDay entity from a domain service it will only return BookOfDay entities, and no child entities. Since this is not what we want we can decorate the Book property of the BookOfDayMetadata class with the Include attribute. We’ll also have to configure the domain service method for getting the BookOfDay entities to include the Book entities too … but we’ll do that in the next step.

   1: internal sealed class BookOfDayMetadata
   2: {
   3:     // Metadata classes are not meant to be instantiated.
   4:     private BookOfDayMetadata()
   5:     {
   6:     }
   7:     //Include the book for the object graph
   8:     [Include]
   9:     public Book Book { get; set; }
  10:     public int BookID { get; set; }
  11:     public DateTime Day { get; set; }
  12: }

imageCustomize the Domain Service Methods

The BookClubService class (generated in step 3) contains a series of methods that will be exposed to the Silverlight client. You should see a series of methods to retrieves the entities and a few methods to insert, update and delete Book entities. While this code is generated we can modify the code without risk of it being overwritten. (The domain service generated class is not one that is regenerated on the fly.) So we can edit the GetBooks method to return the books in sequence by title.

   1: public IQueryable<Book> GetBooks()
   2: {
   3:     return this.ObjectContext.Books.OrderBy(b => b.Title);
   4: }

Then change the GetCategories method to order the Category entities by the CategoryName.

   1: public IQueryable<Category> GetCategories()
   2: {
   3:     return this.ObjectContext.Categories.OrderBy(c => c.CategoryName);
   4: }

Now change the GetBookOfDays method to include the Book entity and return the most recent BookOfDay entity and its Book.

   1: public IQueryable<BookOfDay> GetBookOfDays()
   2: {
   3:     return this.ObjectContext.BookOfDays.Include("Book").OrderByDescending
   4:         (b => b.Day).Take(1);
   5: }

Build the application and the services will be exposed, the models shared, and the metadata shared to the Silverlight client.

imageConfigure the Data Sources to use ListBox Controls

Now let’s go to the Silverlight client in Visual Studio 2010. Open the Home.xaml View in the designer. Styles have already been applied to the View by my Designer, which yields a nice limageooking control. But we have to hook the functionality (data, buttons, actions, behaviors) up. Let’s start by opening the Data Sources window and verifying that we see the Book, BookOfDay and Category show up under the BookClubContext. These can be dragged to the design surface which then creates a Domain Data Source (DDS) and a DataGrid in the View’s XAML. The DDS calls the GetBooks method in the domain service in the web project and binds the results to the DataGrid. image

We don’t want a DataGrid, though. So lets change the type of control to a ListBox. Click the arrow to the right of the Book in the Data Source window and select Customize. When the Customize Control Binding dialog appears scroll to ListBox, select it, and click the Set Default button. This tells the Data Sources window that we want the ListBox to be the default option when dragging and dropping to the design surface.

Now, go back to the Data Sources window and the Book should now show a different icon that represents the ListBox.

 image

imageDrag the Data Sources to the Design Surface

Drag the Category from the Data Source window to the rectangular Grid panel below the Book Categories title. Then right click the ListBox and choose Reset Layout | All. This makes the ListBox consume all of the space inside of the Grid.

image

Drag the BookOfDay to the BookOfDay Grid and reset the layout to “all”. Then drag the Book to the Book Grid and reset the layout to “all”.

The ListBox controls are now created, aligned, and bound to the newly created DDS controls. The Silverlight client is also now wired up to retrieve the data for these bindings from the domain service class we created in the previous steps.

Now drag the Book from the Data Sources window onto the DataPager control. This binds the DataPager to the same DDS that the Book ListBox is bound to, thus enabling paging.

imageApply the DataTemplates

Now it is time to apply the DataTemplates for the 3 ListBox controls. These DataTemplates were created in advance by our designer as resources and are quite simple. For example, the DataTemplate for Book looks like this:

   1: <DataTemplate x:Key="BookItemTemplate">
   2:     <StackPanel Orientation="Horizontal">
   3:         <TextBlock Text="{Binding Title}" Margin="8,0"/>
   4:         <TextBlock Text="(by "/>
   5:         <TextBlock Text="{Binding Author}"/>
   6:         <TextBlock Text=")"/>
   7:     </StackPanel>
   8: </DataTemplate>

We can apply the DataTemplates to the ListBoxes using the new Visual Studio 2010 tooling for imageapplying resources. Select the Category ListBox in the designer, go to the Properties window, and find the ItemTemplate property. Click the gray arrow in the right hand side of the ItemTemplate’s value box and the following dialog should appear. This shows all of the matching options, which in this case are the DataTemplates within scope that can be applied to this ListBox’s ItemTemplate property. Select the CategoryItemTemplate. Now repeat the process and apply the BookOfDayItemTemplate and the BookItemTemplate to their respective ListBox controls. Our ListBox controls are now laid out, styled, bound and templated.

imageApply Filters

We want to filer the books by the selected category and by the title or author (whichever is selected in the combobox and value typed into the TextBox above the Book’s ListBox). We can do this through the Visual Studio 2010 tooling by first going to the Document Outline window and selecting the bookDomainDataSource. Open the Properties window, find the FilterDescriptors property, and click the button (the one with the 3 dots).

When the Collection Editor for the FilterDescriptors appears click the Add button to add a new filter. This filter will make sure the books are filtered by the selected category. Set the PropertyPath to the string “CategoryID” (without quotes). Then click the square next to the Value property, click the Apply Data Binding options, and the binding dialog appears. For the Source select the ElementName binding and the categorylistBox, as shown below.

image

Now for the Path select the SelectedItem property as shown below. We just created a filter so only books for the selected category will appear.

image

Now we need to create a filter by the partial name entered for the author or title. Add another filter descriptor and set the Operator to Contains (we want to do partial matching of the title or author). Bind the PropertyPath to the cboSort combobox’s SelectedItem.Content property, as shown below.

image

Then bind the TextBox named txtFilter and to its Text property, as shown below.

image

These steps created the filters but there are 2 additional steps we need to take. First, we need to go to the XAML of the filter for the category and set the Path to SelectedItem.CategoryID. (The tooling does not support the free form entry of the CategoryID in the filter dialog.) Next, I want the FallBackValue for the same filter to be set to 1. This way if a category is not selected the filter will be applied to the first category. When you are done, your XAML for the filters  should look like this:

   1: <riaControls:DomainDataSource.FilterDescriptors>
   2:     <riaControls:FilterDescriptor Operator="IsEqualTo" PropertyPath="CategoryID" Value="{Binding ElementName=categoryListBox, Path=SelectedItem.CategoryID, FallbackValue=1}" />
   3:     <riaControls:FilterDescriptor Operator="Contains" PropertyPath="{Binding Path=SelectedItem.Content, ElementName=cboSort}" Value="{Binding ElementName=txtFilter, Path=Text}" />
   4: </riaControls:DomainDataSource.FilterDescriptors>

imageApply Sorting

The next step is to apply the sorting. Select the bookDomainDataSource from the Document Outline window, go to the Properties window, and find the Sort Descriptors property. Click the button and when the sort dialog opens, add a new SortDescriptor. Here we want to sort by the selected value in the cboSort combobox. Click the PropertyPath’s binding icon and select the Apply Data Binding option. Set the Source to cboSort and set the Path to SelectedItem.Content.

image

Your XAML for the SortDescriptor should look like this:

   1: <riaControls:DomainDataSource.SortDescriptors>
   2:     <riaControls:SortDescriptor PropertyPath="{Binding Path=SelectedItem.Content, ElementName=cboSort}" />
   3: </riaControls:DomainDataSource.SortDescriptors>

imageBind the Book Control

The next step is to bind the selected book (from the ListBox) to the BookControl. The BookControl is already created (in a separate XAML file in my project). It contains the layout to display and edit the book’s property values. All it needs is a book for its DataContext to bind to.

Select the BookControl, go to the Properties window, and find the DataContext property. Click the binding button next to the DataContext property and choose the Apply Data Binding option. use the binding picker to bind to the ElementName of bookListBox and the Path of SelectedItem. Now our BookControl is bound to the selected book.

image

imageBind the Submit Button

We can support saving changes made by the user by binding the Submit button control to the bookDomainDataSource control’s SubmitChanges method. Select the btnSubmit control, go to the properties window, and find the Command property. Click the binding button next to the property and choose the Apply Data Binding option. Set the Source to the bookDomainDataSource and set the Path to the SubmitChangesCommand. (This command is part of the DDS you created when you dragged the Book from the Data Sources window onto the design surface.)

image

image

Now it is time to run the application. Click the login link and register a username and a password.You will need this information to log into the application so you can edit the book details.

This will take advantage of the authentication that is set up by default by WCF RIA Services. This includes an auth database, services to log in and register users, log in controls, and wiring up the services to the Silverlight client.

image

image

Once you log in you can use the application to:

  • choose different categories and watch the books get filtered
  • change the sorting for the books
  • filter the books by partial name of the author or title
  • select a book and view the book details in the book control
  • page through the books
  • edit details of a book
  • submit the changes for the book

You might notice when you edit the book details that some fields are in bold. These fields have validation attributes applied to them for required fields. If you remove the text from the ASIN TextBox the control will be highlighted in red. This means the validation condition not been met. If you hover over the upper right corner of the TextBox on the red triangle you will see a message that explains the problem.

image 

image

This application stepped you through creating the fictitious Online Book Shelf application using RIA Services. if you have 10 minutes, you can watch me follow these steps (rather quickly with some variations) from the keynote from the Silverlight 4 launch using the following link. I begin 28 minutes in and spend about 9 1/2 minutes on the demo.

You can download the source for the completed version of the application or the starter from these links:

NOTE: After you download the zip files, make sure you unblock them. Also, I recommend cleaning the solution before you start working through the steps.

image

Several people contributed heavily to this keynote demo and application including Deepesh Mohnani, Jeff Handley, Dinesh Kulkarni, and Nikhil Kothari. Thank you all for your huge contributions!

Now for something Different …

If you made it this far in the post, you can even watch a pre-keynote warmup (tongue in cheek) from me and Ward Bell.