Up Tour of DevForce Silverlight
DevForce 2010 Resource Center » DevForce overview » Tour of DevForce Silverlight » Tour of DevForce Silverlight - Part 1

Tour of DevForce Silverlight - Part 1

Last modified on August 15, 2012 17:21

Part 1: From "File New" to a working DevForce application - In Part 1 of this series we'll see how quickly you can get started writing a Silverlight application using DevForce.  In this tutorial we'll create a new application, add an entity model, and load query results into a grid.  


Tip  For best results, code along with the step-by-step video.

Getting started

Let's begin by creating a new project. We'll be using Visual Studio 2010 and targeting Silverlight 4. You'll need to have DevForce 2010 installed in order to follow along.

output_html_m5ac6f9a0.png
First, select File | New | Project from the main menu.

You'll notice that several project templates are available under DevForce 2010. Select DevForce Silverlight Application, name your project "SimpleSteps", and click OK.

If you select a targeted framework other than .NET Framework 4 at the top of the New Project dialog, the DevForce 2010 templates will not be visible.

output_html_3147e094.png
The template creates two projects for us.

The first one is a Silverlight 4 project named SimpleSteps.

The second one is an ASP.NET project named SimpleStepsWeb. It will host our Silverlight application as well as the DevForce application server.

Create an entity model

In this tutorial, we are going to use the NorthwindIB database that is provided as part of the DevForce installation. If you have Microsoft SQL Server 2008 or 2005 installed locally, then it will automatically show up for you. This is true for the Express Edition of SQL Server as well.

We'll use an Entity Framework Entity Data Model for accessing data. Right-click on the SimpleStepsWeb project and select Add | New Item….

In the Add New Item dialog, you will find the ADO.NET Entity Data Model under Data. We'll name ours NorthwindIB and click Add. You can also locate the template quickly by simply typing "ADO" into the Search Installed Templates field in the upper right of the dialog.

output_html_5599d41a.png

Next we'll select Generate from database and then click Next.

You'll need to create a connection to NorthwindIB that is specific to your environment. Click New Connection to set one up.

Note that, by default, the wizard will save your entity connection settings under the name “NorthwindIBEntities”. This will also become the name of the EntityManager you will use in your application to retrieve and cache entities. Accept this default name, and click Next to continue

The Entity Data Model Wizard wants to know which objects to include in the model. For this tutorial we’ll just create entities backed by Tables. Expand the Tables node and select the following tables, leaving the others unchecked:

  • Customer
  • Employee
  • Order
  • OrderDetail
  • Product
  • Supplier

We'll leave the rest of the settings at their default values and click Finish.

You might receive a Security Warning at this point. Don't worry. DevForce is using Visual Studio's templating system to generate code based upon the Entity Data Model we just created. We recommend checking Do not show this message again and then clicking OK.

output_html_150ebc1e.png

A number of things happen after the template executes.

First, the visual designer opens and we can explore the Entity Data Model or “EDM”. We'll come back to it in a moment.

Second, a number of assembly references are added to both of our projects. The names of DevForce assemblies all begin with "IdeaBlade".

output_html_726666b1.png

Third, the DevForce template that guides the generation of our business model is added to SimpleStepsWeb. Notice that its name matches the name of our EDM and has the file extension "tt". If you expand the template node, you'll see a file named NorthwindIB.IB.Designer.cs. This is the code that was generated by DevForce using the template.

output_html_m668ec998.png
NorthwindIB.IB.Designer.cs is also linked to our Silverlight project. You can see it in the Shared Code folder. Note the shortcut icon overlay indicating that the file is linked rather than being copied.

You might be wondering why the file is linked instead of having the Silverlight project simply reference the Web project. There are several reasons:

  1. The Web project targets the .NET Framework and Silverlight projects cannot reference .NET Framework projects.
  2. We don’t want to copy the file, because it is likely to change and the copies would very quickly get out of sync.
  3. As we develop our app, we are likely to include code or configuration settings in the web project that are only for server-side use, and which we don’t want exposed on the client machine.

But sharing the generated code file by means of a link allows the class definitions to be shared between both projects, without creating undesirable side-effects. With our entities defined in a shared file that will be compiled and included in both our server- and client-side assemblies, we will be able to access and use our entities on both the client (Silverlight) and the application server.

Let's go back to the visual designer for our EDM. The diagram represents a conceptual view of the model entities and their associations. This view was generated based on the schema of the NorthwindIB database. DevForce uses this conceptual model to generate the corresponding .NET entity classes.

Entity Framework does a fairly good job of naming these items to meet our expectations. If we examine the Navigation Properties1 on the Employee class, we see that it created a property, Orders, that returns a collection of Order instances.

output_html_76cfe45.png

output_html_m4a877af7.pngHowever, in some cases the EDM designer really didn’t know what to do. Notice the properties on Employee that are named Employee1 and Employee2. One of the properties represents the manager for a given employee and the other represents a collection of the employee's direct reports. If we right-click on Employee1 and select Properties, we can examine the details for the Employee1 property.

(Note that we've also selected the Categorized icon output_html_299ce02b.png on the toolbar in the Properties panel so that you can see how the properties are grouped.)

Notice that the Multiplicity for Employee1 is "* (Many)" and that the Return Type is "Collection of Employee". This lets us know that this property returns the collection of direct reports rather than the single Employee representing the current Employee’s manager. Since we want our model to be both clear and rich in meaning, let's rename this property.

We'll change the value of Name to "DirectReports". When we do so, the value of Display Name will change as well.

Next, we select the property Employee2 on the Employee class. By examining its details, we confirm that it represents the employee's manager. We'll change its Name to "Manager".

Display Name is not a property native to Entity Framework. It’s actually an attribute that DevForce adds to the EDM. DevForce extends both the Entity Framework EDM and the Entity Framework Visual Designer with its own XML attributes and properties. All of the DevForce extensions are grouped under the “DevForce Code Generation” category.

We now have a functional business model, and we can turn our attention to the user interface.

Run a query

Let's say that we want a form in our application for viewing the details of employees.

We'll begin by creating a new class that will be a logical representation of our form. This class will be our view model. We'll use the powerful data binding system in Silverlight to bind an instance of the view model to the currently existing MainPage.xaml. The XAML file and its associated code-behind are known as the view. This approach is very popular in Silverlight development and is part of the design pattern known as Model-View-ViewModel.

Right-click on the Silverlight project, SimpleSteps, and select Add | Class ….

Name the new class MainPageViewModel and then click Add. (We're choosing this name to remind us that it is an abstraction of the view MainPage.xaml.)

We'll need a collection of all the employees. So let's add

C#
public ObservableCollection<Employee> Employees { get; private set; }
VB
Public Property Employees() As ObservableCollection(Of Employee)
 Get
   Return m_Employees
 End Get
 Private Set(ByVal value As ObservableCollection(Of Employee))
    m_Employees = value
 End Set
End Property

and we'll need to add a using or Imports statement also:

C#
using System.Collections.ObjectModel;
VB
Imports System,Collections.ObjectModel

ObservableCollection<T>  is a special type that raises an event whenever items are added or removed. This is known as change notification and is an important part of Silverlight's data binding system.

Employee is one of the entity classes that was generated by DevForce.

output_html_m113b4736.png
Now, we want to populate our new collection with data. We gain access to the data by means of a class known as the EntityManager. DevForce generates a special EntityManager for us that is extended to support our specific database. Let's jump back to the visual designer for NorthwindIB.edmx for a moment. If we click somewhere on the design surface, in empty space and not on an entity, then we'll see the details for the EDM as a whole in the Properties panel.

We're interested in the property EntityManager Name. This is the name of our model-specific class.

Let's add a constructor to MainPageViewModel and create an instance of our EntityManager. We'll also initialize the Employees collection.

C#
public MainPageViewModel() {
  Employees = new ObservableCollection<Employee>();
  var mgr = new NorthwindIBEntities();
}
VB
Public Sub New()
  Employees = New ObservableCollection(Of Employee)()
 Dim mgr = New NorthwindIBEntities()
End Sub

If you examine the properties of the NorthwindIBEntities manager, you will discover that many of them correspond to the entities in our EDM. In fact, we see a property named Employees that returns the type EntityQuery<Employee>. These properties are our "hooks" for querying the data in our database. For example, let’s say that we want all of the employees whose last name begins with 'B'. We could use LINQ to create the query:

C#
var query = from employee in mgr.Employees
  where employee.LastName.StartsWith("B")
  select employee;
VB
Dim query = From employee In mgr.Employees _
  Where (employee.LastName.StartsWith("B")) _
 Select employee

In our case, we want the all of the employees in the database. We don't need to filter the set, so we can simply say:

C#
var query = mgr.Employees;
VB
Dim query = mgr.Employees

This abbreviated form is equivalent to:

C#
var query = from employee in mgr.Employees
  select employee;
VB
Dim query = From employee In mgr.Employees _
 Select employee

We want to emphasize that the Employees property produces a query and not a collection of objects. In order to get results of the query, we need to execute it. Just defining the query does not actually cause the database to be hit. Additionally, note that our query lives on the Silverlight client, and that Silverlight prohibits remote synchronous operations such as querying a server for data. We’ll have to fetch the Employees asynchronously.

First, we'll need two more using statements:

C#
using IdeaBlade.Core;
using IdeaBlade.EntityModel;
VB
Imports IdeaBlade.EntityModel
Imports IdeaBlade.Core

and then we'll execute our query like this:

C#
query.ExecuteAsync(op => op.Results.ForEach(Employees.Add));
VB
query.ExecuteAsync(Sub(op) op.Results.ForEach(Sub(emp) Employees.Add(emp)))

That's a dense statement, so let's unpack it.

ExecuteAsync() has a number of overloads: we are choosing one that expects a callback. In other words, we'll pass a method to it that will be executed on the client when the results of the query are returned. This method should have a single argument of type EntityQueryOperation<T>. In this specific case, T is Employee. You don't need to understand much about EntityQueryOperation<T> for the moment, except that it has a property, Results, that contains the set of employees that our query returns.

We've provided this method inline with the lambda expression:

C#
query.ExecuteAsync(op => op.Results.ForEach(Employees.Add));
VB
Sub(op) op.Results.ForEach(Sub(emp) Employees.Add(emp))

The variable op is the instance of EntityQueryOperation<T> that will be passed in.

We are using the extension method ForEach() to iterate over the results and add them to the ObservableCollection<Employee> (Employees) in MainPageViewModel. The ForEach() “extension method” is a part of IdeaBlade.Core. It executes a given method once for each member in Results, and so we use it to call the Add() method on Employees.

In a nutshell, this single line:

C#
query.ExecuteAsync(op => op.Results.ForEach(Employees.Add));
VB
query.ExecuteAsync(Sub(op) op.Results.ForEach(Sub(emp) Employees.Add(emp)))

executes our query asynchronously, and when completed adds the results to a collection on our view model.

The complete code for our view model now looks like this:

C#
using IdeaBlade.Core;
using IdeaBlade.EntityModel;

namespace SimpleSteps {
 public class MainPageViewModel {
   public MainPageViewModel() {
      Employees = new ObservableCollection<Employee>();
      var mgr = new NorthwindIBEntities();
      var query = mgr.Employees;
      query.ExecuteAsync(op => op.Results.ForEach(Employees.Add));
    }
   public ObservableCollection<Employee> Employees { get; private set; }
  }
}
VB
Imports IdeaBlade.Core
Imports IdeaBlade.EntityModel
Namespace SimpleSteps
 Public Class MainPageViewModel
   Public Sub New()
      Employees = New ObservableCollection(Of Employee)()
     Dim mgr = New NorthwindIBEntities()
     Dim query = mgr.Employees
      query.ExecuteAsync(Sub(op) op.Results.ForEach(Sub(emp) Employees.Add(emp)))
   End Sub
   Private privateEmployees As ObservableCollection(Of Employee)
   Public Property Employees() As ObservableCollection(Of Employee)
     Get
       Return privateEmployees
     End Get
     Private Set(ByVal value As ObservableCollection(Of Employee))
        privateEmployees = value
     End Set
   End Property
 End Class

End Namespace

Instead of a callback to the query we could instead have added a handler for the Completed event.  The handler for the event would look like this:

C#
private void GotEmployees(object sender, EntityQueriedEventArgs<Employee> args ){
  args.Results.ForEach(Employees.Add);
}
VB
Private Sub GotEmployees(ByVal sender As Object, ByVal args As EntityQueriedEventArgs(Of Employee))
  args.Results.ForEach(Employees.Add)
End Sub

Display the data

For this next step, we're going to need the Silverlight Toolkit from Microsoft. It provides a number of additional controls that are not a part of the basic Silverlight SDK. If you don't have already have the Toolkit installed, you can download the latest release from:

http://silverlight.codeplex.com/

Be sure to download the Silverlight 4 release.

Please note that the Silverlight Toolkit is not the same thing as Silverlight Tools. The Toolkit is mostly a set of controls whereas Silverlight Tools contains the primary SDK and Visual Studio integration bits.

Let's open MainPage.xaml.

You'll see the text "Hello DevForce". If you look in the Document Outline panel (or even in the XAML pane), you will see that the root element is a UserControl.

output_html_m717f44e1.png

output_html_10305f7e.pngSelect the UserControl either by clicking on it in the Document Outline or by clicking on the blank space in the design surface.

Next, click on the small square on the lower right corner of the bounding box. Drag this down and to the right to increase the design-time size of the user control. Resize it so that it fills the majority of the design surface. This won't affect the size of the form when it's running: it only changes the size inside the designer.

The "Hello DevForce" text is the label on a TextBlock control. Delete this control by clicking on the text in the designer area and then pressing the Delete key.

output_html_m3e861b58.pngNext, locate the DataGrid control in the Toolbox and drag it anywhere on to the design surface. Dragging the control to the design surface does several things for us. First, it adds a reference in the project to the necessary assemblies from the Silverlight Toolkit. Second, it adds a namespace alias to the XAML file so that we can access the control in the markup.

The initial placement, alignment, and margins of the data grid are not very useful. Right-click on the data grid and select Reset Layout | All.

If you examine the XAML, you'll see that the data grid is represented by the markup:

XAML
<sdk:DataGrid AutoGenerateColumns="False" Name="dataGrid1" />

We want to use this control to view our employees. We have to make two changes to the XAML for the DataGrid:

  1. Change the value of its AutoGenerateColumns property to “True”; and
  2. Bind its ItemsSource to the Employees collection on our view model.
XAML
<sdk:DataGrid AutoGenerateColumns="True"
   Name="dataGrid1"
   ItemsSource="{Binding Employees}"/>

Ok, there's one more thing we need to do before we can run the application. We need to tell the view, MainPage.xaml, about our view model, MainPageViewModel.

Right-click on MainPage.xaml and select View Code. We're going to create an instance of our view model and set it as the data context for MainPage.xaml whenever it loads. The data context is what Silverlight uses to resolve data bindings. We've told Silverlight to bind the data grid to Employees, but Silverlight doesn't yet know what "Employees" means. We have to give it a context so that it can correctly interpret the binding.

Modify the constructor for MainPage.xaml.cs to this:

C#
public MainPage() {
  InitializeComponent();
  Loaded += delegate { DataContext = new MainPageViewModel(); };
}
VB
Public Sub New()
  InitializeComponent()
  DataContext = New MainPageViewModel()
End Sub

Now we are ready to run the application!

output_html_178eec17.png

Notice that it takes just a second before the data is displayed in the data grid. This is because the Silverlight client is making an asynchronous call to the application server to retrieve the data.

This concludes Part 1 of the tour of DevForce Silverlight.

Learn More

We've briefly covered a lot of topics here.  Here are some links to what we've covered, and additional information we hope you find useful.

Prerequisites

The user interface for the application built during this tour uses a DataForm component supplied by the Silverlight 4 Toolkit (different from the Silverlight 4 Tools!). You can download the Toolkit here:

http://silverlight.codeplex.com/

To work with this application, as all DevForce 2010 Silverlight applications, you will need Visual Studio 2010, the Silverlight 4 runtime (SilverlightTools.exe), and DevForce installed.

  1. ^  Navigation Properties are properties that allow you to "navigate" to other entities in the model. For example, if you have an instance of an Employee you can navigate to any Order instances that are associated with that employee. 
Created by DevForce on July 15, 2010 13:01

This wiki is licensed under a Creative Commons 2.0 license. XWiki Enterprise 3.2 - Documentation. Copyright © 2015 IdeaBlade