SpriteHand
Module Border
  Silverlight 4 Beta, RIA Services... and Beer!
Module Border
Location: BlogsAndy's Blog    
Posted by: host 11/18/2009 2:27 PM

Silverlight 4 Beta and Visual Studio 2010 add much in the line of Rapid Application Development. Besides adding support for the Cider XAML designer and properties window, we now have Data Sources Window support for RIA Services.

In this (quite long) blog post, I’ll walk through the creation a Line of Business-type application using Silverlight 4, RIA Services, and Visual Studio 2010.

Contents

The Ingredients. 1

Getting Started. 1

Adding a New Page. 2

Adding the Database and Image Assets. 3

Creating the Data Access Layer. 4

Creating the Domain Service Class. 6

Using the Data Sources Window for RAD Data Forms. 8

Adding a ComboBox to the Details View.. 10

Saving Changes. 15

Adding New Records. 16

Deleting Records. 17

Adding Validation. 17

Custom Validation + Shared Classes. 19

 

The Ingredients

Ensure you have all of the required ingredients:

Visual Studio 2010 Beta 2

Silverlight 4 Tools Beta for Visual Studio 2010

The Sample Code for this Walkthrough

Getting Started

Create a new Silverlight Business Application Template named BeerDB.

The Business Application Template creates a solution with .NET RIA Services enabled, and includes a Silverlight Navigation application with separate “Views” and a MainPage. Run the application by hitting F5 and note the project that was generated. At the top-right of the screen are “home” and “about” links. When you click these, you are brought to the appropriate View in the project. Close the browser window to stop debugging.

Adding a New Page

Let’s add in a new View to display our Beer Maintenance page. Right-click the Views subfolder in the BeerDB (Silverlight) project and select Add/New Item. Select Silverlight Page and name this page “BeerMaintenance.xaml”

Now we need to add a link from the Main Page to our new View. In Solution Explorer, find MainPage.xaml in the Silverlight project and open it. In the Document Outline window (View/Other Windows/Document Outline), find and select the Link1 and Divider1 elements.

Copy and Paste this XAML to add in a new HyperlinkButton and Rectangle Divider, and set the NavigateUri property to our new BeerMaintenance page.

    NavigateUri="/BeerMaintenance" TargetName="ContentFrame" Content="Beers"/>

Run the project. Note that the new “beers” link is available and you can navigate between all of the Views.

Adding the Database and Image Assets

We’ll use a simple file-based SQL server database, placed in our App_Data folder of the Web project. The database includes Uri’s to images of Beer Labels, which we’ll also bring into the project.

In the BeerDB.Web Project (Web Application),  right-click the App_Data folder and select Add/Existing Item. Browse to the “Database.mdf” file (from the download for this walkthrough).

In the BeerDB.Web Project (Web Application), right-click the ClientBin folder and select Add/New Folder. Name the new folder Images. Right-click the Images folder and select Add/Existing Item. Browse and select all of the beer label images (from the download for this walkthrough.

Your BeerDB.Web project should now look something like this:

Creating the Data Access Layer

We’ll use the Entity Framework for our Data Access Layer, but note that we have lots of options here (LINQ to SQL, POCO, etc).

In the BeerDB.Web Project (Web Application), right-click and select Add/New Item. Select ADO.NET Entity Data Model and name the model BeerModel.edmx

Select Generate from Database for the first Step

In the next step, note that our Database.mdf is automatically selected. Enter “BeerEntities” for the connectionstring settings.

In the next step, select the Beers and Brewers tables and name the Model Namespace “BeerModel”:

Click “Finish” to complete the Entity Data Model Wizard. Note our simple database schema. Close the BeerModel.edmx and then Build the Project.

Creating the Domain Service Class

Right-click the BeerDB.Web project and select Add/New Item. Select Domain Service Class and name the class BeerService.

NOTE: If the next dialog comes up empty, just close and Rebuild the Solution, then repeat the above step.

In this step, we want to be able to edit and add Validation metadata, so check Enable Editing for both tables and “Generate associated classes for Metadata.”

Using the Data Sources Window for RAD Data Forms

Build the application to ensure everything is sync’ed up (there is a good amount of code generation happening with RIA Services!)

Back in the Silverlight application, find the BeerMaintenance.xaml View and open it. Open the Data Sources Window (from the menu, select Data/Show Data Sources). Select the Beer Entity under the BeerContext:

 

 

 

 

 

 

 

 

 

 

 

 

… and drag the Beer entity to the design surface.

A DataGrid and DomainDataSource are added to the page XAML. Also, look at the codebehind file (BeerMaintenance.xaml.cs) and note that a LoadedData event handler has been added to check for and raise any errors.

Run the project and notice the Grid gets populated:

Next we’ll add a “Details” View. Click the Beer drop-down in the Data Sources Window and select “Details” view:

Drag the Beer entity from the Data Sources onto the design surface, just under the DataGrid. Note that a Details view is automatically generated for you:

NOTE: We could also the the DataForm control for this Details View. However, VS2010’s Cider Designer does not support editing of Templates – so we would instead need to use Expression Blend, or hand-edit the template in XAML.

Adding a ComboBox to the Details View

Let’s add a Dropdown (ComboBox) for the Brewers. In the Data Sources Window, select the Brewer Dropdown and the select Customize:

We want to show a ComboBox for the Brewers selection, so select ComboBox and click OK.

Back in the Data Sources window, drop down Brewer again and select ComboBox:

Delete the existing “Brewer Id” TextBox and replace it with a ComboBox by dragging the Brewer entity from the Data Sources window into the Grid Cell.

IMPORTANT NOTE: The following step is a temporary work-around for the Silverlight 4 Beta – there is an issue where the DomainDataSource cannot expose its Type information to the Design Surface. Hopefully a future release will fix this issue! But in the meantime we need to add a d:DataContext attribute as follows:

We need to inform the Design Surface/Properties Window that our main Grid container will be bound to a Beer at runtime. We can do this using a design-time DataContext attribute to our container Grid:

        d:DataContext="{d:DesignInstance Type=my:Beer}" DataContext="{Binding ElementName=beerDomainDataSource, Path=Data}" …

Now we can data bind our ComboBox. Select the new ComboBox and in the Properties Panel, select the Advanced Properties icon next to SelectedItem and then “Apply Data Binding”

We want to bind the SelectedValue of the ComboBox to the Brewer value for the Beer, so select the Brewer property by double-clicking on it:

Then, set the SelectedValuePath to BrewerId:

 

Next, we’d like to display the name of the Brewery in the ComboBox instead of the Id, so change the DisplayMemberPath property to BreweryName:

 

There is one other little thing to take care of for the ComboBox, and this is because of timing issues which I talked about in a previous blog post. In order to make sure that the ComboBox has its Items filled at the time its SelectedItem is bound, we need to make both the Main Beer DomainDataSource and the Brewers DomainDataSource point to the same Data Context.

To do this, add in a Resources section to the page and define a BeerContext…

    <navigation:Page.Resources>

        <my:BeerContext x:Key="beerDomainContext" />
    </navigation:Page.Resources>

Then, find the beerDomainDataSource (you can use the Document Outline to find it) and in the Properties Window, set its DomainContext to the beerDomainContext static resource (remember that you can double-click on the final element you want to bind to once you navigate to it).

Then find the brewerDomainDataSource and again set the DomainContext to the beerDomainContext. Now, both DomainDataSource objects are pointing to a single DataContext.


Run the project, and note that the ComboBox is populated with Brewers, and shows the correct Brewer for each selected row.

Saving Changes

So far we have a simple Master/Detail setup, but we haven’t actually submitted changed back through the Service layer and into the Database.

Add a Button to the UI named btnSave. Double-click this button to get to the event handler in the code-behind.

At the very top of the class file, add a using statement to import the BeerDB.Web namespace (this is the namespace for the RIA Services generated Context and Proxy classes):

using BeerDB.Web;

At the top of the class definition, add a variable to store the Domain Data Source instance for beers:

DomainDataSource _ddsBeers;

In the OnNavigatedTo event handler, get a reference to the beerDomainDataSource in code, and wire up the SubmittedChanges event handler:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    _ddsBeers = this.FindName("beerDomainDataSource") as DomainDataSource;
    _ddsBeers.SubmittedChanges += new EventHandler(_ddsBeers_SubmittedChanges);
}

Handle the SubmittedChanges event so that it shows any exceptions, and shows a Submit Complete message on success:

void _ddsBeers_SubmittedChanges(object sender, SubmittedChangesEventArgs e)
{
    if (e.HasError)
    {
        System.Windows.MessageBox.Show(e.Error.ToString(), "Submit Error", System.Windows.MessageBoxButton.OK);
        e.MarkErrorAsHandled();
    }
    else
        MessageBox.Show("Submit Complete.");
}

Finally, implement the btnSave.Clicked event so that it submits changes to the Beer Domain Data Source:

_ddsBeers.SubmitChanges();

Give the project a run and try Updating some records.

Adding New Records

Add a Reference to the assembly System.Windows.Data.dll. NOTE that in the Silverlight Beta, you may need to manually Browse to the folder C:\Program Files\Microsoft SDKs\Silverlight\v4.0\Libraries\Client to add this assembly.

Add a new Button named btnAddNew and then add the following code in its Click event, which will add a new Record into the Grid. It does this by creating a new Beer object and adding it to the DomainDataSource’s DataView collection. DataView is meant for code-based programmatic access of Data, and you can learn more about that here - http://jeffhandley.com/archive/2009/11/16/domaindatasourceview-again.aspx

 

private void btnAddNew_Click(object sender, RoutedEventArgs e)
{
    // only allow a new row insert on an existing saved row
    if ((_ddsBeers.DataView.CurrentItem as Beer).BeerId > 0)
    {
        Beer newBeer = new Beer();
        _ddsBeers.DataView.Add(newBeer);
        // disable the Grid until user saves
        beerDataGrid.IsEnabled = false;
    }
    else
        MessageBox.Show("Save the current NEW Beer before adding a new one.");
}

Deleting Records

We can delete a record by calling Remove on the DataView Collection of the DomainDataSource class. Add a new button named btnDelete, and add implement it’s Click event handler as follows:

private void btnDelete_Click(object sender, RoutedEventArgs e)
{
    _ddsBeers.DataView.Remove(_ddsBeers.DataView.CurrentItem);
    _ddsBeers.SubmitChanges();
    beerDataGrid.IsEnabled = true;
}


Adding Validation

We get some basic data type validation automatically, with no custom coding required. For example, if you run the application and try to enter a character value in the Alcohol Content field, you’ll see a validation error is displayed, because this field is a decimal type.

If we want to add other validation, we can do so in the BeerService.metadata.cs file, inside the Web project of the solution. When we add validation to this metadata file, the validation is automatically copied into the client-side Silverlight project – giving us validation at both client and server side. This is important for performance and to prevent attacks that spoof the client side.

Open BeerService.metadata.cs and add Validation attributes to the BeerMetadata class to validate string lengths, required fields, and formatting:

    public int BeerId;

    [Required(ErrorMessage = "You must enter a Beer Name.")]
    [StringLength(100, ErrorMessage = "Beer Name must be less than 100 chars.")]
    public string BeerName;

    public Brewer Brewer;

    public Nullable BrewerId;

    [StringLength(100, ErrorMessage = "Color must be less than 100 chars.")]
    public string Color;

    [StringLength(200, ErrorMessage = "Image Url must be less than 200 chars.")]
    public string ImageUrl;

    public Nullable IntroductionDate;

    [StringLength(200, ErrorMessage = "More Info Url must be less than 200 chars.")]
    [RegularExpression(@"^http\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$", ErrorMessage = "More Info Url must be a valid Url.")]
    public string MoreInfoUrl;

Let’s also add in a ValidationSummary control so that we can see all validation errors in our Details form. Right-click the Toolbox in Visual Studio and select Choose Items. Select the ValidationSummary control:

Next, drag a ValidationSummary control from the Toolbox inside the Grid containing the Details form. You should add a new RowDefinition to the Grid so that the ValidationSummary can show at the bottom of the other fields.

Run the application and test the validation of the various fields:



Custom Validation + Shared Classes

Besides the “canned” validation shown above, we can also define Custom Validation based on any kind of logic we prefer. Since the validation must execute on both the Server and the Silverlight Client, we place this Custom Validation in a Shared class. Shared Classes are automatically compiled into the Silverlight client when they are created on the Server side web project.

 

In this example, we’ll add a validation method that only allows certain colors. Note that, in a real world example, we would probably define this in a “lookup table” instead of code.

Add a new Class named CustomValidateColors.shared.cs to the BeerDB.Web project. Note that simply by adding the “.shared.cs” suffix, this will cause RIA Services to automatically copy and compile the class to the Silverlight application.

Add a new static method to the class which validates that the color of a beer is within a given list. Note the signature of the method.

public static ValidationResult IsValidBeerColor(object value,
    ValidationContext context)
{
    string[] colors = { "Light", "Amber", "Dark" };

    if (colors.Contains(value))
    {
        return ValidationResult.Success;
    }
    else
    {
        return new ValidationResult(context.DisplayName + " must be Light, Amber, or Dark.");
    }
}

You can now use this new validation method on a property in the metadata class. Open BeerService.metadata.cs and add in a CustomValidation attribute which uses the IsValidBeerColor method to validate the beer color.

[StringLength(100)]
[CustomValidation(typeof(CustomValidateColors), "IsValidBeerColor")]
public string Color;

Run the project and note the validation message for Color.

 




 

Permalink |  Trackback

Comments (10)   Add Comment
Re: Silverlight 4 Beta, RIA Services... and Beer!    By Anonymous on 12/2/2009 5:05 PM
I'm still having a problem getting the combobox to set to the selected value all the time. I followed all your instructions, and it works some of the time. In fact, even your example sometimes fails. If you change the brewerId to 3 for beerId 1 and run your sample, when the form initially loads, it doesn't bind the correct selectedValue (it defaults to the first in the list).

Re: Silverlight 4 Beta, RIA Services... and Beer!    By Anonymous on 2/1/2010 2:22 PM
You just saved me an overnight getting this done.. Thank You!!!

Re: Silverlight 4 Beta, RIA Services... and Beer!    By Anonymous on 4/19/2010 7:44 PM
This is such a great tutorial - very nicely done, and more fun than connecting to AdventureWorks. Thanks so much for taking the time to write such a detailed post with step-by-step instructions on this!

Re: Silverlight 4 Beta, RIA Services... and Beer!    By Anonymous on 5/3/2010 8:32 AM
I have to say this is just one more incredible disappointment in an incredible series of disapointments in trying to come up to speed in VS2010 and Silverlight.

First I tried downlloading your application and running it. I got 41 errors. So then I wanted to build the app using VS2010 and Silverlight 4. I can't load the database because it's version 655 and my versioon of SQL express only supports up to version 612.

This is only the 15th or 16th time I have tried to run a sample of anything to do with vs2010 and silverlight AND NOTHING EVER WORKS!!!!!!!!

I know this is Microsoft and not your responsibility but come on. When is this all going to come together.

I have lost all myc redibility with my client and I cannot even make a simple data driven application with comboboxes work. It's pathetic.

Re: Silverlight 4 Beta, RIA Services... and Beer!    By Anonymous on 5/3/2010 2:17 PM
Part of the problem may be that this walkthrough was created with a pre-release version of WCF RIA Services. I'll see what I can do to update to the latest version, but AFAIK the changes were pretty small between this and final release.

If you post some of your specific error info here, maybe someone can be of help.

-Andy

Re: Silverlight 4 Beta, RIA Services... and Beer!    By Anonymous on 5/13/2010 1:29 PM
Wow Andy you are patient. I had bookmarked this post and wanted to look at something again and the ALL CAPS comment caught my eye. I was the one that posted the comment on 4/19. If that is real it is up there on my list of bizarre comments. Seriously you take the time (YOUR time) to put together all this info with sample download and you get hassled over it? Anyway, it made me just want to write in again and say thanks again for this post I'm still referring back to it, and keep up the good work! - Mickie

Re: Silverlight 4 Beta, RIA Services... and Beer!    By Anonymous on 6/7/2010 1:40 PM
great post Andy.....this is exactly what I have been trying to accomplish for quite sometime.

I was wondering if you have ever gotten this sample to work properly with Silverlight 4 RC and Visual Studio 2010.

I am stuck on the section where you add the resource section to the page to define the BeerContext. It does not recognize the property Resources for type Page.

Being new to Silverlight, I am sure it is something simple that I am not doing.

Thank you again. Great job!

Re: Silverlight 4 Beta, RIA Services... and Beer!    By Anonymous on 7/21/2010 10:33 PM
Hello,Thanx for these post, I seek for help if you please,I make WCF Service that collect the databases available in the SQL Server to DataGrid,so How can I collect the tables of this selected Database
in another DataGrid???

Re: Silverlight 4 Beta, RIA Services... and Beer!    By Anonymous on 7/26/2010 1:45 PM
Very nice demonstration. I am working on Silverlight and RIA services for past 2 month. This is far more practical demo...

Cheerz
Jaweed Khan

Finally a combox example that works    By Anonymous on 8/30/2010 8:31 PM
Thanks Andy. There are so many incomplete or out-of-date examples for placing comboboxes in the forums. I did not use your code, but followed along with Silverlight 4 RC and it works quite well.

For Microsoft: a data 'form' without an easy combo box is not very worthy of LOB (Line Of Business) applications. This works, but it is still too difficult.

For anyone looking at the toolkit DataForm and wanting a combobox: Give it up. Even their sample doesn't include one, which should be a big hint.

Well done, Andy!



Title:
Comment:
Add Comment   Cancel 
Module Border Module Border
Module Border
  Subscribe
Module Border
RSS   Twitter
Module Border Module Border
Module Border
  Diversions
Module Border

TALKING RAGDOLL
This Windows Phone 7 App was created using Silverlight, the  Physics Helper Library,  and the Farseer Physics Engine. It gets interesting when you import your friends photos and have your way with them!

MORE INFO



DROPPYPOP
This Windows Phone 7 game was created using Silverlight, the  Physics Helper Library,  and the Farseer Physics Engine.
DEMO

MORE INFO



BOSS LAUNCH
This physics game won first place in the Server Quest Contest. Created using Silverlight 2, the Physics Helper Library,  and the Farseer Physics Engine.
PLAY IT

MORE INFO



DESTROY ALL INVADERS
A scrolling shooter game where the objective is to destroy the invading UFO's flying over a neighborhood of your choosing. Imagery provided by Microsoft Virtual Earth. Created using Silverlight 2.
PLAY IT

INFO AND CODE



PHYSICS HELPER DEMOS
These demos were created for the Physics Helper Library, which makes it easy to create physics games and simulations using Expression Blend, Silverlight, and the Farseer Physics Engine.
PLAY IT

INFO AND CODE



HOOK SHOT
This little basketball game took first place in the TeamZoneSports Silverlight Contest. Created using Silverlight 2 and the Farseer Physics engine.
PLAY IT

MORE INFO



SORT THE FOOBARS
A game where you need to sort the good foobars from the bad ones. Created using Silverlight 2 and the Farseer Physics engine.
PLAY IT

MORE INFO



POLYGON PHYSICS DEMO
A demo showing polygon physics where the user draws physics objects with the mouse. Created using Silverlight 2 and the Farseer Physics engine.
PLAY IT

MORE INFO



SILVERLIGHT ROCKS!
Destroy the asteroids before they destroy your ship! Created using Silverlight 2.
PLAY IT

INFO AND CODE



FISH GAME
A simple game of harpoon-the-fish. Written using the AJAX Sprite Toolkit.
PLAY IT

INFO AND CODE

Module Border Module Border
Module Border
  Search_Blog
Module Border
Module Border Module Border
Module Border
  Blog_Archive
Module Border
Module Border Module Border
Copyright (c) 2012 andy.beaulieu.com - Login