Peter McGrattan’s Weblog

Silverlight, WCF, ASP.NET, AJAX, Graphics, RIA

Silverlight 2.0 Stock List Demo – Part 2

Posted by petermcg on April 24, 2008

Edited on 26/June/2008 : Code download updated to support Silverlight 2 Beta 2

Edited on 20/October/2008 : Code download updated to support Silverlight 2 RTW

Part Two : From XML file to DataGrid via WCF – (Code download)

Part 1 of this post showed a simple Silverlight application that populates a DataGrid with sample financial stock information read from an XML file extracted from a .xap package using LINQ to XML.

This post shows how to get the same stock information from an XML file and bind it to a DataGrid, but this time the data does not come from the client deployment package but instead from a WCF web service.

Here’s a look at the Visual Studio 2008 solution for Part 2 :

Solution Structure

Now that the data is coming from the server, the Stocks.xml file containing 1000 sample stocks is located under the App_Data folder as part of the web site.

Also added to the web site is the WCF web service ‘StockService’. Support for WCF web services is provided in the System.ServiceModel namespace new to Silverlight 2, for a good introduction to WCF in Silverlight 2 have a look here, be sure to note the required change from wsHttpBinding to basicHttpBinding for Beta 1.

StockService implements the GetStocks() method and returns a generic list of Stock objects using the XmlFileStockService class that remains unchanged. In order to get the path to open the XML file from within the WCF service the HostingEnvironment.ApplicationPhysicalPath property is used. In ASMX services the same goal could be achieved using HttpContext.Current.Server.MapPath, however WCF services are host agnostic so unless your web site is running in aspnetCompatibilityMode the HttpContext will be null.

The Stock type is able to be returned and consumed from GetStocks() because it has been marked with the [DataContract] attribute, making it serializable by a serializer such as the DataContractSerializer :

public class Stock
    public string Symbol { get; set; }
    public double Bid { get; set; }
    public double Ask { get; set; }

If these attributes are removed and you try to ‘Add a Service Reference’ to the StockService web service from the Silverlight client application an exception is thrown with the message : ‘Metadata contains a reference that cannot be resolved’.

Our Silverlight client application is manifest by the StockListDemo.App project. ‘Add Service Reference Support’ and Web Services Client functionality is again new to Silverlight 2 and this project takes advantage of that by adding a Service Reference to our WCF StockService called WcfStockService, this is also the final part of a new namespace for the generated proxy in Reference.cs. You can view Reference.cs by clicking on ‘Show All Files’ when the WcfWebService service reference is selected, some of the generated code is worth a look, notice for example that the Stock class implements the INotifyPropertyChanged interface.

The UI for the Silverlight client is still defined in Page.xaml and still consists mainly of a DataGrid control. We are no longer relying on setting AutoGenerateColumns="True" due to a bug in Beta 1. If you specify AutoGenerateColumns="true" at present and then bind to a collection with a Count of 0 and exception is raised with the message "Enumeration has either not started or has already finished", to avoid this exception we define our own columns of type DataGridTemplateColumn as follows :

<data:DataGrid x:Name="StocksGrid"
        <data:DataGridTemplateColumn Header="Symbol">
                    <TextBlock Text="{Binding Symbol}" />
        <data:DataGridTemplateColumn Header="Bid">
                    <TextBlock Text="{Binding Bid}" />
        <data:DataGridTemplateColumn Header="Ask">
                    <TextBlock Text="{Binding Ask}" />

With the web service in place and the UI designed, all that remains is the code in Page.xaml.cs and StockTicker.cs that calls the web service and populates the UI with the results, firstly Page.xaml.cs :

public partial class Page : UserControl
    private readonly StockTicker stockTicker = new StockTicker();

    public Page()

        StocksGrid.ItemsSource = stockTicker.StockList;


Notice the order in which things are happening here : we are binding the DataGrid to the empty StockList collection property first, then forwarding an asynchronous call to the webservice using the GetStocksAsync() method of the stockTicker field. Because the collection the DataGrid is binding to is an ObservableCollection<WcfStockService.Stock>, the DataGrid will populate itself when this collection notifies that it has changed. Download the entire project using the link at the start to see this in action. The code for the StockTicker class is below:

public class StockTicker
    private ObservableCollection<WcfStockService.Stock> stockList = new ObservableCollection<WcfStockService.Stock>();
    public ObservableCollection<WcfStockService.Stock> StockList
        get { return stockList; }

    public void GetStocksAsync()
        BasicHttpBinding binding = new System.ServiceModel.BasicHttpBinding();
        binding.MaxReceivedMessageSize = int.MaxValue;

        EndpointAddress endpoint = Utils.GetHostEndpointAddress("StockService.svc");

        WcfStockService.StockServiceClient proxy = new WcfStockService.StockServiceClient(binding, endpoint);
        proxy.GetStocksCompleted += new EventHandler<WcfStockService.GetStocksCompletedEventArgs>(OnGetStocksCompleted);

    private void OnGetStocksCompleted(object sender, WcfStockService.GetStocksCompletedEventArgs e)
        e.Result.ForEach(stock => StockList.Add(stock));

The StockList collection is initialised when the class is instantiated and the property is populated in the handler for the web service’s GetStocksCompleted event. In order to use the ForEach(Action<T> action) generic method to populate the collection, the Collection Type for the proxy generation code has been changed from the default of Array to System.Collections.Generic.List:

Proxy Collection Type

The handler for the GetStocksCompleted event is wired up in the GetStocksAsync() method along with the creation of objects for the webservice binding and endpoint. The endpoint address is not hardcoded but instead retrieved based on the Uri of the current HtmlPage in the custom Utils.GetHostEndpointAddress method. Also notice that we are setting the MaxReceivedMessageSize property of our binding object, in fact this is the whole reason we are creating a Binding object and an EndpointAdress object and using them in the creation of the StockServiceClient instead of just calling the service’s default parameter-less constructor. The MaxReceivedMessageSize property is initially set to 65536 (64 kilobytes), if you try to return more data than this from a WCF web service without increasing this limit at present, a QuotaExceededException is thrown with the message MaxReceivedMessageSizeExceeded :

Quota Exceeded Exception

For more on this have a look here, especially the second post. The Stocks.xml file contains 1000 stock objects after all so to enable all this data to be returned from the service the MaxReceivedMessageSize property is set to int.MaxValue although it doesn’t need to be set that high for production where DOS issues could be a concern. Interestingly this property is actually of type long or Int64 but if you try to set it to long.MaxValue for example, an ArgumentException is thrown with the message MaxReceivedMessageSizeMustBeInIntegerRange. As a last word on the MaxReceivedMessageSize property, notice that there is a setting in the ServiceReferences.ClientConfig file generated by adding a Service Reference :

<binding name="BasicHttpBinding_IStockService" maxBufferSize="65536"
    <security mode="None" />

There is a known bug that changing these values has no effect in Beta 1, you have to change the property in code as shown above, this will obviously be resolved at some point in a future release.

Now the Silverlight UI is wired up to the WCF service via the StockTicker and the results appear in the DataGrid things are looking good. To prove that the INotifyPropertyChanged interface on the generated Stock class and the ObservableCollection of those Stocks is working as expected, a textbox and button have been added to allow modification of the DataGrid SelectedItem’s Symbol name. Notice that the code in the handler for the button’s Click event merely changes the value of the selected Stock’s Symbol property and the DataGrid updates automatically. This is purely for educational value of course, normally a symbol name would not change :

Stock List DataGrid

To progress with our sample financial RIA stock ticker application the next area to look at is updating the Stock prices, to do this we could call the web-service at a specified interval, but this is not ideal. What we really want is not to have to ‘pull’ updates from the server but have the server ‘push’ updates to the listening client. There is support for this type of duplex communication with the application’s host of origin in Silverlight 2 Beta 1 provided by the Sockets class in the System.Net networking namespace. Depending on feedback this will be the subject of a future post.


2 Responses to “Silverlight 2.0 Stock List Demo – Part 2”

  1. mdavey said

  2. Great sample Peter – thanks for sharing!


Sorry, the comment form is closed at this time.

%d bloggers like this: