SpriteHand
Module Border
  Most recent blog entries
Module Border
.NET RIA Services... and Beer!
Andy's Blog By Andy Beaulieu on 9/29/2009 3:57 PM

Like most .NET Developers, I do a lot of Line of Business application programming, and I’m very excited about .NET RIA Services. In this (very long) blog post, I’ll update my Beer DB Demo using  .NET RIA Services and the Silverlight Business Application Template. In the past, I’ve used the Beer DB for several talks and demos, including a Silverlight 1.1 Alpha Demo named Andy’s Fridge, and a Silverlight and LINQ to SQL demo.

While there is a ton of great information out there on .NET RIA Services, I found many details hard to find and I hope this walkthrough will be helpful to people encountering the same issues I did. Note that this was created using the .NET RIA Services
July 2009 Preview – so if you’re using this with a later release there may be breaking changes.

DOWNLOAD THE SAMPLE CODE

Here is a look at what the completed app looks like – a simple Master/Detail interface with validation and Insert/Update/Delete operations:

Contents

Getting Started. 2

Adding a New Page. 5

Adding the Database and Image Assets. 7

Creating the Entity Data Model 7

Creating the Domain Service Class. 9

Querying using DomainDataSource. 11

Sorting and Filtering using DomainDataSource. 12

Adding a DataForm (Details View). 13

Customizing the DataForm in Blend. 15

Adding Validation. 20

Custom Validation and Shared Classes. 21

Styling the Application. 22

Displaying the Product Image. 23

Debugging and Error Handling. 24

 

Getting Started

1.       Ensure you have all of the required setup components (available from http://silverlight.net/getstarted/

a.       Microsoft Visual Studio 2008

b.      Microsoft Expression Blend 3

c.       Silverlight 3 Tools for Visual Studio

d.      .NET RIA Services (this walkthrough created with July 2009 Preview)

e.      A copy of the Beers Database and Images. These are available in the ZIP download, under \BeerDB.Web\ClientBin\images and \BeerDB.Web\App_Data.

2.       Create a new “Silverlight Business Application” named BeerDB.


3.       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 template 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.


4.       In Solution Explorer, right-click the BeerDB (Silverlight) project and select properties. Note the .NET RIA Services link, which is pointing the Silverlight project to the Web project in the solution. This link is required because, as we’ll see, automatic code and proxy generation is performed when the solution is compiled. For example, when we add a new server-side domain method to retrieve data, a proxy is created to call that method.
 

Adding a New Page

1.       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”


2.       In Solution Explorer, find MainPage.xaml in the Silverlight project. Right-click it and select “Open in Expression Blend”

3.        In the Objects and Timeline panel (or on the artboard), find and select the Divider1 and Link2 elements. Then Right-click and Copy, then Right-click and Paste.


4.       Change the text for this newly copied link to “beers” – and in the Properties Panel, change the NavigateUri to “/BeerMaintenance”



5.       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

1.       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).

2.       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.

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

Creating the Entity Data Model

1.       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


2.       Select Generate from Database and click Next


3.       On this step, select Database.mdf for the data connection, and Save entity connection settings in Web.Config. Change the Connection settings to “BeerEntities” and click Next.


4.       Select the Beers and Brewers Tables in this step and enter “BeerModel” for the Model Namespace. Then Click Finish.


5.       Note our simple database schema. Close the BeerModel.edmx and select Ctrl+Shift+B to build the solution.

Creating the Domain Service Class

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


2.       Be sure that the BeerEntities Entity Framework model is selected (if it is not available, make sure you did a rebuild!) Check the Beers and Brewers entities, Enable Editing, and check the “Generate associated classed for metadata” checkbox.


Querying using DomainDataSource

1.       Back in the BeerDB (Silverlight) project, open the BeerMaintenance.xaml page.

2.       At the top of the page, add in a new xmlns for the current project. This will allow access to the generated proxy classes from the web project.

xmlns:BeerDB.Web="clr-namespace:BeerDB.Web"

3.       Add in a Resources section to the navigation page, and add an instance of the beer Domain Context. Note: we need to create a single instance of the beer domain context to avoid issues with nested listbound elements such as ComboBox and ListBox.

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

4.       Add in a DomainDataSource control from the toolbox, and tweak it like so –

a.       Add in a DomainContext that points to our static resource BeerContext

b.      Set AutoLoad to True

c.       Set the QueryName to Beers

d.      Handle the LoadError and LoadedData events

<
riaControls:DomainDataSource x:Name="ddsBeers"   
    DomainContext="{StaticResource beerDomainContext}"
    AutoLoad
="True"  
    QueryName="GetBeers"  
    LoadError="ddsBeers_LoadError"
    LoadedData
="ddsBeers_LoadedData">
</
riaControls:DomainDataSource>

5.       Drag in a DataGrid from the toolbox and tweak it so that it binds to the ddsBeers Domain Data Source.

<
data:DataGrid x:Name="grdBeers" ItemsSource="{Binding Data, ElementName=ddsBeers}">
</
data:DataGrid>

6.       In the code-behind file, implement the ddsBeers_LoadError and ddsBeers_LoadedData methods so that they raise any exceptions that occur during processing (see the section Debugging and Error Handling for more info).

private
void ddsBeers_LoadError(object sender, LoadErrorEventArgs e)
{
    if (e.Exception != null)
        throw e.Exception;
}

private void ddsBeers_LoadedData(object sender, LoadedDataEventArgs e)
{
    if (e.Error != null)
        throw e.Error;
}

7.       Run the project – you should see a DataGrid with Beers data.

Sorting and Filtering using DomainDataSource

1.       To sort our Beers by BeerName, we can use a SortDescriptor on the DomainDataSource. First add in another xmlns namespace at the top of BeerMaintenance.xaml:

xmlns:riaData="clr-namespace:System.Windows.Data;assembly=System.Windows.Ria.Controls"

2.       Now we can use the Sort Descriptor by adding it inside the DomainDataSource control. In this example, we are sorting by BeerName:

<riaControls:DomainDataSource x:Name="ddsBeers"   
    DomainContext="{StaticResource beerDomainContext}"
    AutoLoad="True"
    QueryName="GetBeers"  
    LoadError="ddsBeers_LoadError"
    LoadedData="ddsBeers_LoadedData">

    <riaControls:DomainDataSource.SortDescriptors>
        <riaData:SortDescriptor Direction="Ascending" PropertyPath="BeerName" />
    </riaControls:DomainDataSource.SortDescriptors>

</
riaControls:DomainDataSource>

3.       Note that we can also add filtering declaratively, by using a FilterDescriptor. Add in a TextBox named txtFilter, along with a label control and place these at the top of the DataGrid:

<StackPanel Orientation="Horizontal">
    <TextBlock Text="Filter: "/>
    <TextBox x:Name="txtFilter" Width="100" />
</
StackPanel>

4.       Now we can add a FilterDescriptor to our DomainDataSource and filter on BeerName. The value of the filter is bound from the txtFilter.Text value using a ControlParameter.

<riaControls:DomainDataSource x:Name="ddsBeers"   
    DomainContext="{StaticResource beerDomainContext}"
    AutoLoad="True"
    QueryName="GetBeers"  
    LoadError="ddsBeers_LoadError"
    LoadedData="ddsBeers_LoadedData">

    <riaControls:DomainDataSource.SortDescriptors>
        <riaData:SortDescriptor Direction="Ascending" PropertyPath="BeerName" />
    </riaControls:DomainDataSource.SortDescriptors>

    <riaControls:DomainDataSource.FilterDescriptors>
        <riaData:FilterDescriptorCollection x:Name="DataSourceFilters">
            <riaData:FilterDescriptor PropertyPath="BeerName" Operator="StartsWith">
                <riaData:ControlParameter ControlName="txtFilter" PropertyName="Text" RefreshEventName="TextChanged" />
            </riaData:FilterDescriptor>
        </riaData:FilterDescriptorCollection>
    </riaControls:DomainDataSource.FilterDescriptors>

</
riaControls:DomainDataSource>

Adding a DataForm (Details View)

A DataForm can quickly add Update, Insert, and Delete functionality to an application.

1.       Open BeerMaintenance.xaml in Blend. Place the grdBeers Grid in a StackPanel and add a DataForm into the StackPanel, so that the resulting XAML resembles the following:

<StackPanel Orientation="Vertical">

    <data:DataGrid x:Name="grdBeers" ItemsSource="{Binding Data, ElementName=ddsBeers}">
    </data:DataGrid>

    <dataFormToolkit:DataForm>
    </dataFormToolkit:DataForm>

</
StackPanel>

2.        Add the following attributes to the DataForm:

<dataFormToolkit:DataForm x:Name="dataForm1"
            ItemsSource="{Binding Data, ElementName=ddsBeers}"
            CommandButtonsVisibility="All" AutoEdit="True"
            AutoCommit="True"
            EditEnded="dataForm1_EditEnded"
            DeletingItem="dataForm1_DeletingItem" >
    <d:DataContext>
        <BeerDB:Beers></BeerDB:Beers>
    </d:DataContext>
</
dataFormToolkit:DataForm>

a.        x:Name=”dataForm1”  - this is the ID of the DataForm in code.

b.        ItemsSource=”{Binding Data, ElementName=ddsBeers}”  - this is the runtime databinding source for the form to get data. Since this is the same data source as the DataGrid, they will stay in sync.

c.        CommandButtonsVisibility=”All”  - this shows all of the Edit and Paging buttons on the DataForm.

d.        AutoEdit=”True”  - this allows the user to edit the data in the form without explicitly selecting an “Edit” command button.

e.        AutoCommit=”True”  - this automatically commits changes to the DataForm when the user selects a different row.

f.         EditEnded Event – handle this so that we can commit updates.

g.        DeletingItem – handle this so that we confirm if the user wants to delete an item.

h.        d:DataContext – this is what Blend uses at Design Time to determine what binding context is available. We set this to an instance of the Beers class so that we can bind fields for the Beer using Blend’s design tools.

3.        In the code-behind file for this page, import the BeerDB.Web namespace so that we can access the proxy classes generated from the server-side context.

using BeerDB.Web;
using System.Windows.Ria.Data;


4.        Add an instance of the BeerContext as a class-level variable.

BeerContext _beerContext;

5.        In the OnNavigatedTo event handler, get a reference to the beerDomainContext page resource and wire up an event handler for the CollectionChanged event.

// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    // Our main Data Context is in the Page's Resource section
    _beerContext = this.Resources["beerDomainContext"] as BeerContext;
    // We need to handle CollectionChanged for Delete's performed on the DataForm
    ddsBeers.DataView.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(DataView_CollectionChanged);
}


6.        Implement the following event handlers to Update/Insert and Delete beer records from the DataForm. Note that we need to handle the CollectionChanged event in order to Delete records, and the EditEnded event handles both Insert and Update operations.

private void dataForm1_EditEnded(object sender, System.Windows.Controls.DataFormEditEndedEventArgs e)
{
    dataForm1.CommitEdit();

    // is this a NEW beer? If so we need to default the RowVersionId
    Beers beer = (dataForm1.CurrentItem as Beers);
    if (beer.BeerId == 0)
    {
        beer.RowVersionId = new byte[1];
    }

    if (e.EditAction == DataFormEditAction.Commit)
        _beerContext.SubmitChanges(SubmitChangesComplete, null);
}

void DataView_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    // We need to handle this event for Deletes, since EditEnded is not called on a delete.
    if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove
        && (e.OldItems[0] as Beers).BeerId > 0)
        _beerContext.SubmitChanges(SubmitChangesComplete, null);
}

void SubmitChangesComplete(SubmitOperation op)
{
    if (op.HasError)
        throw op.Error;
}

7.        Run the project and test the Add, Update, and Delete methods of the DataForm.

Customizing the DataForm in Blend

1.        Note that, when we added the DataForm, we included the following “d:DataContext” attribute:

    <d:DataContext>
        <BeerDB:Beers></BeerDB:Beers>
    </d:DataContext>
  
This informs Blend of the type of data that we will be binding to the DataForm at run-time, so that it can support design time data binding information. Anytime a property is prefixed with “d:”, it is defined in Blend’s namespace and is generally used to set design time properties.

2.        Right-click BeerMaintenance.xaml and select “Open in Expression Blend”

3.        In the Objects and Timeline Panel, find dataForm1. Right-click it and select Edit Additional Templates/Edit EditTemplate/Create Empty.



4.        On the “Create DataTemplate Resource” dialog, accept the defaults and click OK.

5.        Resize the Grid in the data template so that it is about 500 pixels wide and 400 pixels high.

6.        Increase the number of rows in the Grid so that there are 6 rows. You can do this by clicking in the left-hand border of the Grid on the arboard:
 

7.        Increase the number of columns in the Grid so that there are 2 columns. You can do this by clicking in the top border of the Grid on the arboard:


8.        Add a TextBlock into the first row and column of the Grid. Ensure that its Margins are set to 0, set its HorizontalAlignment to Left and VerticalAlignment to Center. Change the text property to “Beer Name:”


9.        Add a TextBox into the first row and second column of the Grid. Ensure that its Margins are set to 0, set its HorizontalAlignment to Left and VerticalAlignment to Center. Your Grid should now look something like this:


10.     Next we’ll create the databinding for the TextBox. Select the Advanced Property Options control (the little white square) to the right of the Text property for the TextBox.


11.     Select the Data Binding option from the popup menu.


12.     On the Create Data Binding Dialog, select the BeerName field. Note that this is on the “Explicit Data Context” tab.


13.     Repeat the steps above to add TextBlocks, TextBoxes, and Data Bindings for the Color, Alcohol, ImageUrl, and MoreInfo properties. Put a placeholder in for the Brewery Label (later on we’ll use a ComboBox for this field). The resulting XAML in the Data Template should look similar to the following:

<Grid x:Name="grdBeerDetails" Grid.Column="1">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="40" />
        <RowDefinition Height="40" />
        <RowDefinition Height="40"/>
        <RowDefinition Height="40"/>
        <RowDefinition Height="40" />
        <RowDefinition Height="40" />
    </Grid.RowDefinitions>
    <TextBlock x:Name="txtBeerNameLabel" Margin="0,0,4,0" VerticalAlignment="Top" Grid.Column="0" Grid.Row="0" Text="Name:" />
    <TextBox x:Name="txtBeerName" VerticalAlignment="Top" Grid.Column="1" Grid.Row="0" Height="24" Text="{Binding BeerName, Mode=TwoWay}" />

    <TextBlock x:Name="txtColorLabel" Margin="0,0,4,0" VerticalAlignment="Top" Grid.Column="0" Grid.Row="1" Text="Color:" />
    <TextBox x:Name="txtColor" VerticalAlignment="Top" Grid.Column="1" Grid.Row="1" Height="24" Text="{Binding Color, Mode=TwoWay}" />

    <TextBlock x:Name="txtAlcoholLabel" Margin="0,0,4,0" VerticalAlignment="Top" Grid.Column="0" Grid.Row="2" Text="Alcohol:" />
    <TextBox x:Name="txtAlcohol" VerticalAlignment="Top" Grid.Column="1" Grid.Row="2" Height="24" Text="{Binding AlcoholContent, Mode=TwoWay}" />

    <TextBlock x:Name="txtBreweryLabel" Margin="0,0,4,0" VerticalAlignment="Top" Grid.Column="0" Grid.Row="3" Text="Brewery:" />

    <TextBlock x:Name="txtImageUrlLabel" Margin="0,0,4,0" VerticalAlignment="Top" Grid.Column="0" Grid.Row="4" Text="Image Url:" />
    <TextBox x:Name="txtImageUrl" VerticalAlignment="Top" Grid.Column="1" Grid.Row="4" Height="24" Text="{Binding ImageUrl, Mode=TwoWay}" />

    <TextBlock x:Name="txtMoreInfoLabel" Margin="0,0,4,0" VerticalAlignment="Top" Grid.Column="0" Grid.Row="5" Text="More Info Url:" />
    <TextBox x:Name="txtMoreInfo" VerticalAlignment="Top" Grid.Column="1" Grid.Row="5" Height="24" Text="{Binding MoreInfoUrl, Mode=TwoWay}" />

</
Grid>


14.     Next we’ll add a ComboBox into the DataForm for the BreweryName selection. Note that we need to query a list of Brewery Names to fill this ComboBox. To query these, add in a new DomainDataSource control just inside the Grid for the Data Template.

<riaControls:DomainDataSource x:Name="ddsBrewers"   
AutoLoad="True"  
QueryName="GetBrewers"  
LoadError="ddsBrewers_LoadError"
DomainContext="{StaticResource beerDomainContext}"
LoadedData="ddsBrewers_LoadedData"/>

15.     Now we can add in a ComboBox into the DataTemplate which uses the ddsBrewers Data Source above. Note the ItemsSource binding which uses the Data Source, and the SelectedItem binding, which uses the Brewers property of the Beer that the record is bound to.

<ComboBox x:Name="cboBrewery"  
  Grid.Column
="1" Grid.Row="3" Height="24"
  ItemsSource="{Binding Data, ElementName=ddsBrewers}"
  SelectedItem="{Binding Brewers, Mode=TwoWay}"
  DisplayMemberPath="BreweryName"/>

16.     Add in the event handlers for the LoadError and LoadedData events for the Brewers query. Note that any errors from the DataContext are not automatically raised, so we need these event handlers to do so.

private void ddsBrewers_LoadError(object sender, LoadErrorEventArgs e)
{
    if (e.Exception != null)
        throw e.Exception;
}

private void ddsBrewers_LoadedData(object sender, LoadedDataEventArgs e)
{
    if (e.Error != null)
        throw e.Error;
}

17.     Run the project, and test the new DataForm template.

 

Adding Validation

1.       Run the application and try setting the Alcohol Content field to a string value. Since the underlying field is a decimal, you get a validation warning. Validation on Data Types is built in automatically to the Data Form.


2.       To add in validation other than data type checking, go to the BeerDB.Web project and open the BeerService.metadata.cs file. Find the BeersMetadata class and add the following attributes to enforce string lengths, required fields, and format. You can also optionally add in the error message to display when the validation errors occur.

internal sealed class BeersMetadata
{

    // Metadata classes are not meant to be instantiated.
    private BeersMetadata()
    {
    }

    public Nullable<Decimal> AlcoholContent;

    public int BeerId;

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

    public Brewers Brewers;

    [StringLength(100)]
    public string Color;

    public EntityState EntityState;

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

    public Nullable<DateTime> 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;

    public byte[] RowVersionId;
}


3.       Run the application and note the new validation for the data form.




Custom Validation and 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.

1.       Add a new Class named CustomValideColors.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.


2.       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.");
    }
}

3.       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;


4.       Run the project and note the validation message for Color.

 

Styling the Application

The Silverlight Business Application Template has a single Styles.xaml resource file which defines the overall look and feel of the application. We can replace this file with a different set of style information, and can even use one of many free styles available from the community.

1.       In the BeerDB (Silverlight) project, expand the Assets folder and note the Styles.xaml file. This contains the style information for our application.


2.       There are many free alternate style templates for RIA Services available on the Expression Community Site. Simply download the ZIP and extract the contents into your Assets subfolder, overwriting the existing Styles.xaml. Below is the application with the Seeing Sound style applied.

Displaying the Product Image

Our database contains links to beer labels, so let’s use these to overlay a beer bottle and create a copy of the “product.” This will give the Details view a bit more spice!

1.       Open BeerMaintenance.xaml in Expression Blend.

2.       Edit the DataForm’s Data Template by right-clicking dataForm1 and selecting Edit Additional Templates/Edit EditTemplate/Edit Current

3.       Right-click grdBeerDetails and select Group Into/StackPanel. Set the StackPanel’s Orientation to Horizontal.

4.        Add a Canvas into the StackPanel, and add two Image controls into the Canvas. Set the Source of the first image to /images/beerBottle.png, and bind the Source of the second image to the ImageUrl property. Align the Images so that the label overlays the bottle. The resulting XAML should look similar to the following:

<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Width="600">
    <Grid x:Name="grdBeerDetails" Width="300" Margin="0,40,40,0">
       
<!-- Grid details removed for brevity -->
    </Grid>
    <Canvas Height="340" Width="200">
        <Image x:Name="imgBeerBottle" Source="/images/beerBottle.png" Width="93" Height="311" Canvas.Left="0" Canvas.Top="0" />
        <Image x:Name="imgBeerLabel" Source="{Binding ImageUrl}" Width="73" Height="95" Canvas.Left="10" Canvas.Top="160" Stretch="Fill" />
    </Canvas>
</
StackPanel>

Debugging and Error Handling

Here are a couple of hints on Debugging and Error Handling with .NET RIA Services.

1.       If an error occurs during a remote call, such as an authorization failure, the Silverlight client will not raise the exception by default. This is because exceptions are silent by default. So be sure to handle the LoadError and LoadedData Events…

<riaControls:DomainDataSource x:Name="ddsBeers"   
    DomainContext="{StaticResource beerDomainContext}"
    AutoLoad
="True"  
    QueryName="GetBeers"  
    LoadError="ddsBeers_LoadError"
    LoadedData
="ddsBeers_LoadedData">
</
riaControls:DomainDataSource>

…and then implement these handlers to check for an error, and minimally raise the exception:

private
void ddsBeers_LoadError(object sender, LoadErrorEventArgs e)
{
    if (e.Exception != null)
        throw e.Exception;
}

private void ddsBeers_LoadedData(object sender, LoadedDataEventArgs e)
{
    if (e.Error != null)
        throw e.Error;
}

2.       In the current (July 2009) version of .NET RIA Services, some exceptions are not properly raised to the Silverlight client. When this happens you will generally get the following error:

Exception has been thrown by the target of an invocation.

To debug this issue, and see the exception on the server side, be sure to enable CLR Exceptions – in Visual Studio, select Debug/Exceptions, and check the Thrown checkbox for “Common Language Runtime Exceptions.”



Comments (13)

ComboBox in DataForm
Andy's Blog By Andy Beaulieu on 9/24/2009 8:14 AM


I ran into a baffling data binding issue when using a DataForm containing a ComboBox recently which caused me to spin my wheels for way too long. Luckily,
Keith Jones was nice enough to set me straight and give me a solution.

I have a DataForm with a ComboBox in its EditTemplate. This is bound to a DataGrid's SelectedItem in a standard Master/Detail, and it’s all using .NET RIA Services.

I was seeing some kind of weird delay in the binding of the Grid's SelectedItem to the ComboBox. If you clicked on a row, the combobox was not bound properly. But if you clicked on a few rows (3 rows was the magic number), then the ComboBox got bound properly from that point on. It seemed like maybe the ComboBox items were taking forever to load, but in looking at an HTTP trace, there was no data being requested across the wire.

It turns out this was a timing issue with the data binding. The SelectedItem was being evaluated properly, but at the time the ItemsSource of the ComboBox was null. You see, I was using the DataForm’s ContentLoaded event to fill the ComboBox with items, something like this:

<ComboBox x:Name="cboCategory"

SelectedItem="{Binding Brewers, Mode=TwoWay}"

DisplayMemberPath="BreweryName" />

 

void dataForm1_ContentLoaded(object sender, DataFormContentLoadEventArgs e)

{

    ComboBox cboBrewery = dataForm1.FindNameInContent("cboBrewery") as ComboBox;

    cboBrewery.ItemsSource = _beerContext.Brewers;

}


…and while this fills the ComboBox just fine, it does it a bit too late --- the SelectedItem of the ComboBox has already been evaluated. Makes sense, but why would three clicks on the DataGrid set the binding straight? As Keith pointed out to me, the DataForm uses a caching mechanism that starts with 2 empty slots. After the first click, the first cache slot was filled. After the second click, the second cache slot was filled. Then on the third click, the first cache slot is reused – and since it had data by the third click, the data was shown.

The Fix: ComboBox in DataForm

There are probably a dozen ways to do this, but here is what I ended up using. You can also use this method for other list bound controls inside a DataForm such as a ListBox. First, add an instance of your Domain Context inside your page resources. Then have your ComboBox bind its ItemsSource to that context. This is shown highlighted below.

<navigation:Page

  x:Class="TestBeer1.Home"

  <!-- Note I removed some stuff here for brevity -->

  xmlns:testBeer1="clr-namespace:TestBeer1.Web"

  NavigationCacheMode="Enabled"

  Style="{StaticResource PageStyle}">

    <navigation:Page.Resources>

        <testBeer1:BeerDomainContext x:Key="beerDomainContext" />

        <DataTemplate x:Key="DataTemplate1">

            <StackPanel>

                <TextBox Text="{Binding BeerName, Mode=TwoWay, UpdateSourceTrigger=Explicit}" />

 

                <ComboBox x:Name="cboBrewery"

ItemsSource="{Binding Brewers, Source={StaticResource beerDomainContext}}"

                      SelectedItem="{Binding Brewers, Mode=TwoWay}"

                      DisplayMemberPath="BreweryName"

                />

            </StackPanel>

        </DataTemplate>

    </navigation:Page.Resources>

 

    <Grid x:Name="LayoutRoot" >

        <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}" >

            <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">

 

                <data:DataGrid x:Name="grdBeers" Height="200" />

 

                <StackPanel Orientation="Horizontal" Margin="20,20,20,20">

                    <dataControls:DataForm x:Name="dataForm1"

CommandButtonsVisibility="Commit,Cancel" AutoEdit="True"

IsReadOnly="False" Width="300" AutoCommit="True"

EditEnded="DataForm_EditEnded"

EditTemplate="{StaticResource DataTemplate1}" >

                        <d:DataContext>

                            <testBeer1:Beers></testBeer1:Beers>

                        </d:DataContext>

                    </dataControls:DataForm>

                </StackPanel>

            </StackPanel>

        </ScrollViewer>

    </Grid>

</navigation:Page>

… And then it is a matter of getting a reference to the domain context and loading up the data. We can do this in the Loaded event for a page or the OnNavigatedTo event for a View in a Navigation Application…

public partial class Home : Page

{

    BeerDomainContext _beerContext;

 

    public Home()

    {

        InitializeComponent();

    }

 

    // Executes when the user navigates to this page.

    protected override void OnNavigatedTo(NavigationEventArgs e)

    {

        _beerContext = this.Resources["beerDomainContext"] as BeerDomainContext;

 

        _beerContext.Load(_beerContext.GetBeersQuery(), LoadBeersComplete, null);

        _beerContext.Load(_beerContext.GetBrewersQuery(), LoadBrewersComplete, null);

        grdBeers.ItemsSource = _beerContext.Beers;

    }

 

    void LoadBeersComplete(LoadOperation<Beers> op)

    {

        if (op.HasError)

            throw op.Error;

    }

 

    void LoadBrewersComplete(LoadOperation<Brewers> op)

    {

        if (op.HasError)

            throw op.Error;

    }

 

    private void DataForm_EditEnded(object sender, System.Windows.Controls.DataFormEditEndedEventArgs e)

    {

        dataForm1.CommitEdit();

        if (e.EditAction == DataFormEditAction.Commit)

            _beerContext.SubmitChanges(SubmitChangesComplete, null);

 

    }

 

    void SubmitChangesComplete(SubmitOperation op)

    {

        if (op.HasError)

            throw op.Error;

    }

}

 

Comments (4)

Glow Behavior
Andy's Blog By Andy Beaulieu on 9/18/2009 3:38 PM

Some weeks ago, Adam Kinney wrote about a nice workaround for creating a Glow Effect in Silverlight using a DropShadowEffect. Since Glow is a common effect, I thought it would be nice to wrap this into a Behavior. Please note, you wouldn’t want to use this behavior in any kind of animation – because the DropShadowEffect is currently rendered in software and will quickly bring a CPU to its knees.

DOWNLOAD SOURCE

Creating the Glow Effect in Code

To mimic a Glow effect in XAML, we use a DropShadow Effect with ShadowDepth and Direction equal to zero:

<TextBlock Text="Glowing Text" Foreground="White" FontSize="16" FontWeight="Bold">
   <TextBlock.Effect>
        <DropShadowEffect Color="#FFFFFEBB" ShadowDepth="0" Direction="0" BlurRadius="100"/>
    </TextBlock.Effect>
</TextBlock>

We can do the equivalent in code like so:

DropShadowEffect dsEffect = new DropShadowEffect();
dsEffect.Color = _glowColor;
dsEffect.Direction = 0;
dsEffect.ShadowDepth = 0;
dsEffect.BlurRadius = _glowSize;
txtBlock.Effect = dsEffect;

When we apply the Glow Behavior to, say a Rectangle and TextBlock, we get something like this:

Creating the Glow Behavior

1.  Create a new Silverlight application (or Silverlight Class Library)

2.  Add a Reference to System.Windows.Interactivity. This is part of the Blend 3 SDK, which is installed with Blend 3 or available as a separate download here.



3.  Add a new Class file, which inherits from Behavior, and implement like so. Behaviors like this are really simple to create. The AssociatedObject property is the element that the Behavior is dropped on, and you simply handle the Loaded event to tie in the behavior you want. Note that the Category and Description attributes add support in Blend for Tooltips and Categories in the Properties Panel.

public class GlowBehavior: Behavior<FrameworkElement>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);
    }

    private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
    {
        // add in the DropShadow Effect
        DropShadowEffect deffect = new DropShadowEffect();
        deffect.Color = _glowColor;
        deffect.Direction = 0;
        deffect.ShadowDepth = 0;
        deffect.BlurRadius = _glowSize;
        this.AssociatedObject.Effect = deffect;
    }

    private Color _glowColor = Color.FromArgb(255, 255, 250, 190);
    [Category("Glow Effect"), Description("The color of the Glow.")]
    public Color GlowColor
    {
        get
        {
            return _glowColor;
        }
        set
        {
            _glowColor = value;
        }
    }

    private int _glowSize = 20;
    [Category("Glow Effect"), Description("The size of the Glow.")]
    public int GlowSize
    {
        get
        {
            return _glowSize;
        }
        set
        {
            _glowSize = value;
        }
    }
}

For more fun with Behaviors in Blend, check out the Physics Helper Library on Codeplex.

Comments (5)

Physics Helper Update: Fluid Container!
Andy's Blog By Andy Beaulieu on 9/12/2009 8:31 AM


A new version of the Physics Helper is available for download on Codeplex. This includes a new Fluid Container Behavior to simulate water, as well as a few fixes. The Fluid Container Behavior is based on Jeff Weber's Farseer Water Demo, and allows you to make a fluid simulation by applying a behavior to a XAML element.

Video on Fluid Container Behavior
Watch a short video on applying the Fluid Container Behavior in Blend.

Fluid Container Demos
These demos show the Fluid Container Behavior in action. You can also view all of the demos here.

Demo Behaviors 1
Falling Astronaut

Demo Behaviors 5
Day @ the Beach

Using the Fluid Container
Here are some notes on using the Fluid Container Behavior:

  • You normally apply a Fluid Container Behavior to a Rectangle element, since the fluid simulation is limited to a rectangular region. You can apply a color such as a Gradient Fill to the Rectangle, and the waves will take on that fill. Setting the Opacity of the Rectangle to a lower value is recommended as well, for that fluid look.
  • Keep in mind that only physics objects created before the Fluid Container object are involved in the fluid simulation. If you need different layering order, just use the Canvas.ZIndex property.
  • You may need to adjust the Mass property on the PhysicsObjectBehavior to make objects float or sink as needed.
Comments (1)

Adding Behaviors Programmatically
Andy's Blog By Andy Beaulieu on 8/23/2009 7:31 AM

Expression Blend 3 has great design-time support for Behaviors – you can simply drag Behaviors from the Asset Library onto the Artboard (or Objects + Timeline Window), and the Behaviors are applied to an element. But what if you want to add Behaviors through code at runtime? We can do this by using the BehaviorCollection and GetBehaviors method in the System.Windows.Interactivity Namespace…

using System.Windows.Interactivity;


{…}

BehaviorCollection
behaviorCollection = Interaction.GetBehaviors(box);
behaviorCollection.Add(new MouseDragElementBehavior());

Adding Physics Behaviors Programmatically

In a previous blog post, I had a question about adding Behaviors at runtime for the Physics Helper Behaviors. These behaviors are a little different in that they are dependent on a PhysicsControllerBehavior as kind of a “master controller.” There are also dependencies for some of the other Behaviors – for example a PhysicsJointBehavior depends on the existence of a PhysicsObjectBehavior for the bodies it is joining. So there is an additional call necessary for some of the Physics Behaviors (this may be fixed in a future release).

Here is a code example. Suppose you have a Rectangle named “ground” that you want to make a Static Physics Object (one that stays in place, like some ground), and an Ellipse named “ball” that you want to make a physics object.

PhysicsControllerMain _physicsController = LayoutRoot.GetValue(PhysicsControllerMain.PhysicsControllerProperty) as PhysicsControllerMain;

 

// add physics behavior to an ellipse named "ball"

behaviorCollection = Interaction.GetBehaviors(ball);

behaviorCollection.Add(new PhysicsObjectBehavior());

_physicsController.AddPhysicsBody(ball.GetValue(PhysicsObjectMain.PhysicsObjectProperty) as PhysicsObjectMain);

 

// add static body behavior to a rectangle named ground

PhysicsObjectBehavior behPhysObj = new PhysicsObjectBehavior();

behPhysObj.IsStatic = true;

behaviorCollection = Interaction.GetBehaviors(ground);

behaviorCollection.Add(behPhysObj);

_physicsController.AddPhysicsBody(ground.GetValue(PhysicsObjectMain.PhysicsObjectProperty) as PhysicsObjectMain);


The key is the additional AddPhysicsBody call, which informs the PhysicsController that a new object should be added to the simulation.

Adding User Controls Programmatically

Most of the time, you will want to define Joints and other Physics Behaviors inside separate User Controls. This will help keep your assets in manageable parts. You can still add these user controls dynamically through code, and there is an example of this in the Physics Helper download (DemoBehaviors2, which dynamically adds a RagDoll):

// add a user control, then apply physics

ucRagDoll ragdoll = new ucRagDoll();

LayoutRoot.Children.Add(ragdoll);

_physicsController.AddPhysicsBodyForCanvasWithBehaviors(ragdoll.LayoutRoot);


Keep in mind that the Physics Helper caches any Boundaries that it detects (that is, the outline of your Physics Elements). This is because it is an expensive operation to trace the outline of each element. So you should try to have one instance of your Physics Objects on screen at startup so that subsequent instances are added quickly.

More Info on Physics Helper

Physics Helper on Codeplex


Farseer Physics on Codeplex

Physics Helper 3: Now with WPF Support

Coming Soon:Fluid Container Behavior

Comments (6)

Coming Soon: Fluid Container Behavior!
Andy's Blog By Andy Beaulieu on 8/20/2009 2:22 PM
Have you figured out that Behaviors are the greatest thing since sliced bread? You WILL... only a matter of time :) I'm still having fun in my spare time adding to the Physics Helper Behaviors, and coming soon to the library is a Fluid Container Behavior, which can be used to simulate water and waves. I threw this water/ragdoll test together using the new behavior (oh, and no code!):




MUCH of the credit for the Fluid Container goes to Jeff Weber - besides being the creator of the Farseer Physics Engine, he also published an inspiring Water Physics Demo. And he was nice enough to publish the source code as well! So it took about 60 minutes to wrap Jeff's sample code into a Behavior. THANK YOU JEFF!

Comments (7)

Physics Helper 3: Now with WPF Support!
Andy's Blog By Andy Beaulieu on 8/17/2009 1:34 PM
Several people have asked if the Physics Helper Library for Silverlight could also support WPF. While there are lots of similarities between Silverlight and WPF, there are also LOTS of differences, including the way VisualTreeHelper works - which is something the library uses for its boundary detection.

While I had it somewhere on my TO DO list to incorporate WPF support, it had always been on the backburner in favor of other tasks. But thanks to a new contributor to the code, Bill Seddon, I'm happy to say a new version of the Physics Helper Library is available with WPF support!

This library of Behaviors and Controls for Expression Blend makes it very quick to create physics games and simulations in Silverlight and WPF using the Farseer Physics Engine.

DOWNLOAD PHYSICS HELPER 3

VIEW THE DEMOS

Here are the highlights for this release:
  • Special thanks to contributions made by Bill Seddon!

    • WPF Support has been added
    • MagneticBehavior added, allowing two objects to attract
    • Behaviors now Categorized in Blend Asset Folder

  • PhysicsSoundBehavior adds support for buffered sound

  • PhysicsJoint has Min and Max angle limits

  • Silverlight Pinball game sample added (video tutorial coming soon)

Demos using Behaviors

Demo Behaviors 1
Falling Astronaut
Demo Behaviors 2
Rag Doll
Demo Behaviors 3
Truck w/Camera
Demo Behaviors 4
Flying Astronaut
Pinball Game
Pinball Game

Getting Started Videos

I have a couple of quick (10 min) screen casts which show how to use the new Physics Behaviors:

VIDEO ON "THE BASICS": VIEW | DOWNLOAD

VIDEO ON "JOINTS + PROGRAMMING": VIEW | DOWNLOAD


Comments (6)

Physics Behaviors for Silverlight 3!
Andy's Blog By Andy Beaulieu on 7/15/2009 7:21 PM


Today I released an initial version of “Physics Helper 3” to Codeplex. This includes a collection of new Behaviors for Expression Blend which makes it very quick to create physics games and simulations in Silverlight using the Farseer Physics Engine. This release requires Silverlight 3 and Expression Blend 3, which you can get here.

DOWNLOAD PHYSICS HELPER 3

Demos

There are four new demos using Behaviors, plus the original demos depending on the older User Control model. Note that version 3 still supports the User Control model, but I would recommend checking out the new Behaviors model as there is nice design time support in Blend.

VIEW ALL DEMOS

Demo Behaviors 1
Falling Astronaut
Demo Behaviors 2
Rag Doll
Demo Behaviors 3
Truck w/Camera
Demo Behaviors 4
Flying Astronaut

Getting Started Videos

I have a couple of quick (10 min) screen casts which show how to use the new Physics Behaviors:

VIDEO ON "THE BASICS": VIEW | DOWNLOAD

VIDEO ON "JOINTS + PROGRAMMING": VIEW | DOWNLOAD

Enhancing Behaviors with Code

Behaviors are great, but I can't imagine creating a full game using only canned behaviors. So at some point, you will need to add code to do AI, control levels and game state, and other tasks. Here are some pointers to get started with that:

Once you drop a PhysicsController Behavior onto your main Canvas, you can later get a reference to that Physics Controller (the object that contains the simulation context) in code. Suppose your main Canvas is named "LayoutRoot" then you can get a reference as follows:

PhysicsControllerMain _physicsController = LayoutRoot.GetValue(PhysicsControllerMain.PhysicsControllerProperty) as PhysicsControllerMain;

After you have a reference to the PhysicsController, you can modify any of the Farseer Physics Geometry or Body objects by getting a reference throught the PhysicsObjects dictionary:

_physicsController.PhysicsObjects["ball"].GeometryObject.RestitutionCoefficient = 1.3F;

... and you can also get a reference to the oringal XAML UI Element using the uiElement property of the Physics Object:

Ellipse ball = _physicsController.PhysicsObjects["ball"].uiElement as Ellipse;
ball.Fill = new SolidColorBrush(Colors.Red);

Feedback and Issues

This is an initial release and my first swing at Behaviors, so I'm sure there will be issues and suggestions. Please let them fly on the Codeplex Forum, and I hope you have fun! 

Comments (8)

Silverlight 3 Released!
Andy's Blog By Andy Beaulieu on 7/10/2009 12:45 PM

Today, the FINAL RTW version of Silverlight 3 was released! You can get everything you need to get started with Silverlight 3 at
silverlight.net/GetStarted, and the launch site is now live at www.seethelight.com (which features a rather amusing Infomercial). And as always, ScottGu is quick to the draw with his announcement post.

I have added some new posts on Silverlight 3:

Printing in Silverlight 3 with WriteableBitmap – Shows how to use the new WriteableBitmap class to “print” the Silverlight UI or take a screenshot.

Silverlight 3: HitTest with WriteableBitmap - Shows how to do pixel-perfect collision detection between Raster (Image) and Vector (XAML) elements in Silverlight.

Physics Helper 3: Coming Soon! - Shows the soon-to-be-released Physics Helper 3, with support for Behaviors in Blend.

And I have updated the older Silverlight 3 Beta posts so everything is compatible:

Silverlight 3: GPU Acceleration and Bitmap Caching – This is the most exciting feature of Silverlight 3, IMHO!

Silverlight 3: Pixel Shaders and Effects - See how you can create new effects using HLSL.

Silverlight 3: PlaneProjection with Storyboard - Looks at how to display and animate the new 3D Perspective projection.

Comments (0)

Physics Helper 3: Coming Soon!
Andy's Blog By Andy Beaulieu on 7/10/2009 11:08 AM


Silverlight 3 and Blend 3 introduce the concept of Behaviors, which make it easy to add common functionality using drag/drop inside Blend.

I’ve been working on creating a set of Behaviors for the Physics Helper Library, and have made good progress. Using these behaviors, you can very quickly put together physics-based games and simulations with little or no code. (Ok, I don’t really believe in the no-code scenario … but you can do some pretty neat stuff without code). Another new feature in the library is the ability to automatically determine the outline (collision boundary) of raster images (such as a PNG).

I’ll be releasing this updated library soon on Codeplex, but here is a screencast I put together to show the Behaviors in action:

[DOWNLOAD THE VIDEO]

Or click below to view it:

Comments (4)

Module Border Module Border
Module Border
  Subscribe
Module Border
RSS   Twitter
Module Border Module Border
Module Border
  Diversions
Module Border


PHYSAMAJIG
This Windows app was created using Physics Helper XAML, and the Farseer Physics Engine.
DOWNLOAD

MORE INFO



TALKING RAGDOLL
This Windows Phone 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



BOSS LAUNCH
This physics game won first place in the Server Quest Contest. Created using Silverlight , 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.
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 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 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 and the Farseer Physics engine.
PLAY IT

MORE INFO



SILVERLIGHT ROCKS!
Destroy the asteroids before they destroy your ship! Created using Silverlight.
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) 2014 andy.beaulieu.com - Login
cheap Ralph Lauren shirts Ralph Lauren outlet Canada Goose jackets on sale cheap moncler jackets moncler jackets on sale moncler outlet canada goose outlet canada goose outlet canada goose outlet cheap ralph lauren shirts ralph lauren outlet ralph lauren outlet canada goose outlet canada goose outlet kanye west louis vuitton moncler outlet moncler outlet moncler outlet moncler outlet speedy louis vuitton canada goose outlet moncler outlet tiffany outlet moncler outlet speedy louis vuitton kanye west louis vuitton