Someone mailed me to ask whether I had a video on how to put together Silverlight and ADO.NET Data Services.
I don't at the time of writing and I've also got a cold right now ( thank you, Microsoft Manchester office :-) ) so I thought I'd write something rather than record it.
Let's run through a step-by-step thing.
Visual Studio 2008 - File->New->Web Site. I'm going for the filesystem and C# as below;
Now, to make it easy to work with ADO.NET Data Services, I'm going to add in an ADO.NET Entity Data Model for Northwind. That is ... Website->Add->New Item;
I say "yes" to add it to my app_code folder, then select;

and then I can go and add a new ADO.NET Data Service ( again via Website->Add New Item );
and then I can update my service code to read;
public class Service : DataService<NorthwindEntities>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
}
}
and I'm also going to reconfigure my project so that the built-in web server uses a particular port rather than a randomly selected one by selecting the website's properties and changing it;
Then I can add a new Silverlight 2 project here by doing File->Add New Project;
and then accepting the defaults for the Silverlight options;
Now, I need my Silverlight project to call the ADO.NET Data Service from my other project so I do a quick "view on browser" on my Service.svc file just to spin up the web server. Then I can drop to a command line in my c:\demo\BlogPostSL folder and use the datasvcutil.exe tool to generate some proxy code for my Silverlight project;
Then I can pop back to Visual Studio and add this as an existing item to my Silverlight project. I also need to add a reference to;
System.Data.Services.Client
in order to make that project ( with the new proxy code ) compile.
Now, I want to build a little bit of UI for Silverlight to display some data. I want to use the DataGrid so the first thing that I need to do is to add a reference to pick up the DataGrid assembly as well. So, that's another reference to the Silverlight project;
System.Windows.Controls.Data
Now I can go and edit some XAML and build up a little piece of UI;
<UserControl
x:Class="BlogPostSL.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition
Height="8*" />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<data:DataGrid
x:Name="dataGrid"
Margin="10"
AutoGenerateColumns="True"
ItemsSource="{Binding}" />
<Button
Margin="10"
Content="Get Data"
Grid.Row="1"
Click="OnGetData" />
</Grid>
</UserControl>
and then drop some code behind it;
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
void OnLoaded(object sender, RoutedEventArgs e)
{
proxy = new NorthwindEntities(
new Uri("http://localhost:32767/BlogPost/Service.svc", UriKind.Absolute));
}
void OnGetData(object sender, EventArgs args)
{
// I don't think that we can use LINQ here because there's no way then
// to make it asynchronous. So, let's use the manual way of doing things.
DataServiceQuery<Customers> query =
proxy.CreateQuery<Customers>("Customers?$filter=Country eq 'UK'");
query.BeginExecute((asyncResult) =>
{
try
{
IEnumerable<Customers> result = query.EndExecute(asyncResult);
// Doubt if we're on the UI thread so...
Dispatcher.BeginInvoke(() =>
{
ObservableCollection<Customers> data = new ObservableCollection<Customers>();
foreach (Customers c in result)
{
data.Add(c);
}
dataGrid.DataContext = data;
});
}
catch (Exception ex)
{
// TODO
Debugger.Break();
}
}, null);
}
NorthwindEntities proxy;
}
and now clicking on my "Get Data" button gets me some data;
Now, that Orders column isn't really something that I want so I guess the easiest thing to do there is to hide it. I still want the grid to automatically generate columns though so perhaps I can just get this one removed?
public Page()
{
InitializeComponent();
this.Loaded += OnLoaded;
dataGrid.AutoGeneratingColumn += OnGeneratedColumn;
}
void OnGeneratedColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.Property.Name == "Orders")
{
e.Cancel = true;
}
}
That's a bit better in that I've got some data on the screen.
As an aside, where I said in that code above that we "can't write this query with LINQ". That wasn't strictly true. I can write something like;
var query = (DataServiceQuery<Customers>)
from c in proxy.Customers
where c.Country == "UK"
select c;
query.BeginExecute((asyncResult) =>
{ // .......
and that looks to work fine once you get over the cast.
I'll look at updating, inserting, deleting in subsequent posts otherwise this gets very long very quickly.
Posted
Mon, Jun 30 2008 11:35 AM
by
mtaulty