Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / C# 4.0

Simple Silverlight 4 Example Using oData and RX Extensions

Rate me:
Please Sign up or sign in to vote.
5.00/5 (13 votes)
23 May 2010Ms-PL2 min read 78.6K   975   22   19
A simple Silverlight application that uses RX Extensions to communicate with an oData service.

Image 1

Introduction

This is part II to the previous clog (http://openlightgroup.net/Blog/tabid/58/EntryId/98/OData-Simplified.aspx) where we looked at a simple OData example. This time, we will make a simple Silverlight application that talks to an oData service.

Note, for this tutorial, you will also need to download and install RX Extensions from: http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx, and the Silverlight Toolkit from: http://silverlight.codeplex.com.

As with the last tutorial, we will not use a database, just a simple collection that we are creating programmatically. This will allow you to see just the oData parts.

First, open up the project, in Visual Studio 2010 (or higher), from the zip file at the bottom of this link.

Image 2

Select Add, then New Project...

Image 3

Create a new Silverlight Application.

Image 4

Add a Service Reference.

Image 5

Click Discover.

Image 6

Create a reference called wsSampleCustomerData.

Image 7

Next, add assembly references in your Silverlight project to:

  • System.CoreEx
  • System.Observable
  • System.Reactive

Image 8

In the Silverlight project, delete the MainPage.xaml.

Image 9

Open the project in Expression Blend 4 (or higher).

Image 10

In Expression Blend, select File then New Item...

Image 11

Select the UserControl with ViewModel template, and create a file called MainPage.xaml.

Image 12

It will create the ViewModel pages (MainPage.xaml and MainPage.xaml.cs with a MainPageModel.cs View Model page that is already wired-up).

Image 13

Create a folder called Model and a class called Model.cs.

Replace all the code with the following code:

C#
using System;
using System.Linq;
using System.Collections.Generic;
using SilverlightODataSample.wsSampleCustomerData;
using System.Data.Services.Client;

namespace SilverlightODataSample
{
    public class Model
    {
        #region GetCustomers
        public static IObservable < IEvent < LoadCompletedEventArgs> > 
            GetCustomers(int intPage)
        {
            // Create a URI that points to the OData Service
            Uri objUri = new Uri(GetBaseAddress(), UriKind.RelativeOrAbsolute);

            // Set up oData service call
            SampleDataSource SDS = new SampleDataSource(objUri);

            // Construct a Query
            var query = (from SampleCustomerData in SDS.SampleCustomerData
                         where SampleCustomerData.CustomerNotes.Contains("3")
                         select SampleCustomerData).Skip(intPage).Take(10);

            // Set up a DataServiceCollection to hold the results
            DataServiceCollection< CustomerRecord > CustomerRecords = 
                new DataServiceCollection< CustomerRecord >();

            // Set up a Rx Observable (in a variable called observable) 
            // that will contain the results of
            // the "LoadCompleted" event that CustomerRecords will fire
            // When LoadAsync(query) is fired in the following statement
            IObservable< IEvent < LoadCompletedEventArgs> > observable =
                Observable.FromEvent< LoadCompletedEventArgs >(CustomerRecords,
                "LoadCompleted");

            // Execute the LoadAsync on CustomerRecords passing
            // the query that was constructed earlier
            CustomerRecords.LoadAsync(query);

            // Return observable
            return observable;
        }
        #endregion

        #region GetBaseAddress
        private static string GetBaseAddress()
        {
            // This gets the address of the webservice by 
            // getting the AbsoluteUri and then stripping out the 
            // name of the .xap file
            string strXapFile = @"/ClientBin/SilverlightODataSample.xap";
            string strBaseWebAddress =
                App.Current.Host.Source.AbsoluteUri.Replace(strXapFile, "");
            return string.Format(@"{0}/{1}", strBaseWebAddress, @"Service.svc");
        }
        #endregion
    }
}

Image 14

Open MainPageModel.cs and replace all the code with the following code:

C#
using System;
using System.ComponentModel;
using System.Collections.ObjectModel;
using SilverlightODataSample.wsSampleCustomerData;
using System.Data.Services.Client;

namespace SilverlightODataSample
{
    public class MainPageModel : INotifyPropertyChanged
    {
        public MainPageModel()
        {
            // When the Control loads
            // Get the Customers
            GetCustomers();
        }

        #region GetCustomers
        private void GetCustomers()
        {
            // Call the Model to get the Customers
            // Passing in 0 to get the first page
            // Paging could easily be done here
            // You could also pass in other criteria
            Model.GetCustomers(0).Subscribe(p = >
            {
                // Check for an error in the Service
                if (p.EventArgs.Error == null)
                {
                    // loop thru each item in the
                    // DataServiceCollection< CustomerRecord >
                    // Collection
                    foreach (CustomerRecord Customer in
                        (DataServiceCollection< CustomerRecord >)p.Sender)
                    {
                        // Add to the Customer to the colCustomerRecord 
                        // Collection so the View can bind to it
                        colCustomerRecord.Add(Customer);
                    }
                }
            });

        }
        #endregion

        #region CustomerRecord
        // The View will bind to this collection and automatically be notified if 
        // The collection changes. The Designer can bind any UI element that 
        // can hold a collection
        private ObservableCollection< CustomerRecord > _colCustomerRecord
            = new ObservableCollection< CustomerRecord >();
        public ObservableCollection< CustomerRecord > colCustomerRecord
        {
            get { return _colCustomerRecord; }
            private set
            {
                if (colCustomerRecord == value)
                {
                    return;
                }

                _colCustomerRecord = value;
                this.NotifyPropertyChanged("colCustomerRecord");
            }
        }
        #endregion

        #region INotifyPropertyChanged
        // This is a supporting method to raise a notification for any
        // Element that is subscribed to a Property that implements
        // NotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }
}

Image 15

Grab a DataGrid and drop it on the design surface.

Image 16

Widen it so it fills the page.

Image 17

Click on the Data tab so that you see the Data Context.

Image 18

Drag and drop the colCustomerRecord collection onto the DataGrid.

Image 19

Build and run the project.

OData and RX extensions are pretty impressive:

  • RX extensions were used because it decouples the oData Service calls from the View Model. This allows the methods in the model to be easily called by multiple View Models.
  • We are only grabbing the first page of the results, but we could easily implement paging by passing the page number to the method.
  • We are also only creating a simple query. We could easily create a more complex query of the oData Service.

Security

For information on securing your OData Methods, see: Simple Example to Secure WCF Data Service OData Methods.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
Software Developer (Senior) http://ADefWebserver.com
United States United States
Michael Washington is a Microsoft MVP. He is a ASP.NET and
C# programmer.
He is the founder of
AiHelpWebsite.com,
LightSwitchHelpWebsite.com, and
HoloLensHelpWebsite.com.

He has a son, Zachary and resides in Los Angeles with his wife Valerie.

He is the Author of:

Comments and Discussions

 
GeneralMy vote of 5 Pin
Member 96405625-Dec-12 0:19
Member 96405625-Dec-12 0:19 
GeneralAnother excellent article! Pin
mbcrump8-Feb-11 16:09
mentormbcrump8-Feb-11 16:09 
GeneralRe: Another excellent article! Pin
defwebserver8-Feb-11 17:44
defwebserver8-Feb-11 17:44 
GeneralGood article, but I don't think you are using RX Extensions 100% correctly... Pin
User 467791624-May-10 13:50
User 467791624-May-10 13:50 
GeneralRe: Good article, but I don't think you are using RX Extensions 100% correctly... Pin
defwebserver24-May-10 14:01
defwebserver24-May-10 14:01 
GeneralRe: Good article, but I don't think you are using RX Extensions 100% correctly... Pin
User 467791624-May-10 14:51
User 467791624-May-10 14:51 
GeneralRe: Good article, but I don't think you are using RX Extensions 100% correctly... Pin
defwebserver24-May-10 15:23
defwebserver24-May-10 15:23 
GeneralRe: Good article, but I don't think you are using RX Extensions 100% correctly... Pin
User 467791624-May-10 15:53
User 467791624-May-10 15:53 
GeneralRe: Good article, but I don't think you are using RX Extensions 100% correctly... Pin
defwebserver25-May-10 13:33
defwebserver25-May-10 13:33 
GeneralRe: Good article, but I don't think you are using RX Extensions 100% correctly... Pin
User 467791625-May-10 14:08
User 467791625-May-10 14:08 
GeneralNice Article Pin
linuxjr23-May-10 14:49
professionallinuxjr23-May-10 14:49 
GeneralRe: Nice Article Pin
defwebserver23-May-10 15:57
defwebserver23-May-10 15:57 
GeneralGood one.. Pin
Rajesh Pillai21-May-10 3:58
Rajesh Pillai21-May-10 3:58 
GeneralRe: Good one.. Pin
defwebserver21-May-10 4:52
defwebserver21-May-10 4:52 
Thank you for the feedback and the vote!
GeneralThis is nice, though Pin
Sacha Barber20-May-10 21:52
Sacha Barber20-May-10 21:52 
GeneralRe: This is nice, though [modified] Pin
defwebserver21-May-10 1:50
defwebserver21-May-10 1:50 
GeneralRe: This is nice, though Pin
Sacha Barber21-May-10 3:16
Sacha Barber21-May-10 3:16 
GeneralRX Extensions? - Is that like dreadlocks or something??? :-) Pin
Alan Beasley20-May-10 6:09
Alan Beasley20-May-10 6:09 
GeneralRe: RX Extensions? - Is that like dreadlocks or something??? :-) Pin
defwebserver20-May-10 7:39
defwebserver20-May-10 7:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.