Silverlight – Databinding to a Web Service

misc_vol1_049 In the last several posts, I’ve demonstrated various ways of getting data onto the screen.  What I’ve purposely omitted up until this point is how to update this information.

So let’s start by going back to the demo we created in Febuary.

What we ended up with is an application that would display the First name and the last name out of the Person class.

What we want to do today is to update the code so that the person class gets its data from a database on the server using a web service.  So the first thing we’ll want to do is create a web service.

For the purposes of this demo, I created a new database with a new table called “Person.”  Here’s the SQL for the table.

USE [SilverLightTest]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Person](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [First] [varchar](50) NULL,
    [Last] [varchar](50) NULL,
 CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, 
  STATISTICS_NORECOMPUTE  = OFF, 
  IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, 
  ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

Next we need to create our own class to access the data.  Actually, all we are going to do is move the Person class we’ve been using down to the web service and add some stuff to it.

First we need to add an Id property to store the ID field that we have in our table.

Next we’ll need to add the DataContract attribute to the class and the DataMember attribute to the properties.  These two attributes are part of the System.Runtime.Serialization namespace and are what make the class serializable to Silverlight.

The last thing we will need to do is to set this class up so that it can notify controls that are bound to it that the data has changed.  While you may never make use of this code, it is simple to add and will keep you from pulling your hair out when you do need it.

To enable this feature, you will need to have the class inherit from INotifyPropertyChanged.  Once that is done, you’ll need to add the event declaration PropertyChangedEventHandler to your code.  Finally, we’ll want a central method that we can call to tell  the controls that any one of the controls has fired.  This is the OnPropertyChanged method.

Now it’s just a matter of adding calls to OnPropertyChanged in each of our set blocks.  This call will notify the controls that are bound to the property in Silverlight that the property has been changed and the control needs to update its value.  This code will require you to use the System.ComponentModel namespace.

Yes, I know we are doing this on the server and the Silverlight code will be running on the client, but Silverlight has some kind of “magic happens here” that makes this all work.

Here’s the resulting class after the modifications.

[DataContract()]
public class Person : INotifyPropertyChanged
{
    public Person()
    {
    }

    
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, e);
    }

    private int m_id;
    [DataMember()]
    public int Id
    {
        get { return m_id; }
        set
        {
            m_id = value;
            OnPropertyChanged(
                new PropertyChangedEventArgs("Id"));
        }
    }

    private string m_First;
    [DataMember()]
    public string First
    { 
        get{return m_First;}
        set
        {
            m_First = value;
            OnPropertyChanged(
                new PropertyChangedEventArgs("First"));
        } 
    }

    private string m_Last;
    [DataMember()]
    public string Last
    {
        get { return m_Last; }
        set
        {
            m_Last = value;
            OnPropertyChanged(
                new PropertyChangedEventArgs("Last"));
        }
    }


}

 

From here, we create a web service that allows us to access the data.  Since we are using our own class to return the data, the best way of going after the data is with our own DataReader calls.  I’m going to call mine “Service.”  When you add the service, make sure you select “Silverlight-enabled WCF Service” so that it creates all of the attributes you need.

If you rushed ahead, you’ll want to make sure the class has the ServiceContract attribute and the methods have the OperationContract attribute.

Here’s the initial file that gets created for us

[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = 
    AspNetCompatibilityRequirementsMode.Allowed)]
public class Service
{
    [OperationContract]
    public void DoWork()
    {
        // Add your operation
        // implementation here
        return;
    }

}

We are going to change that DoWork() method so that it returns a list of Person objects

public class Service
{
    private string connectionString =
        WebConfigurationManager.
        ConnectionStrings["SilverLightTestConnectionString"].
        ConnectionString);
    [OperationContract]
    public List<Person> GetData()
    {
        List<Person> people = new List<Person>();
        SqlConnection conn = 
            new SqlConnection(connectionString);
        SqlCommand cmd = 
            new SqlCommand("SELECT ID,First,Last FROM Person", conn);
        try
        {
            conn.Open();
            SqlDataReader reader = cmd.ExecuteReader();
            while (reader.Read())
            {
                Person p = new Person();
                p.Id = reader.GetInt32(0);
                p.First = reader.GetString(1);
                p.Last = reader.GetString(2);
                people.Add(p);
            }
        }
        finally
        {
            conn.Close();
        }
        return people;
    }

}

BTW, if you want web services to work reliably, you’d better make sure you are running off of IIS instead of using the file-based asp.net application.

I then added a reference to this web service in my Silverlight application and called it “PersonService".”

Now my startup code in Page.xaml.cs looks like this

public partial class Page : UserControl
{
    public Page()
    {
        PersonService.ServiceClient service = new SilverlightWithWebService.PersonService.ServiceClient();
        service.GetDataCompleted += new EventHandler<SilverlightWithWebService.PersonService.GetDataCompletedEventArgs>(service_GetDataCompleted);
        service.GetDataAsync();
        service.CloseAsync();
    }

    void service_GetDataCompleted(object sender, SilverlightWithWebService.PersonService.GetDataCompletedEventArgs e)
    {
        PersonService.Person p = e.Result[0];
        DataContext = p;
        InitializeComponent();
    }
}

Notice howI wire up the GetDataCompleted event handler?

That event handler was created by the proxy code that was created.  All services are called asynchronously so we have to specify the callback that gets called when it completes.  Once the method gets called, I retrieve the first item from the collection and assign it to the Page’s DataContext.

Notice too that I don’t initialize the components until I have the records.  While it may work to initialize during the constructor, what’s the point?

Well, this post is already considerably longer than I’d like it to be, so we’ll have to wait for the Update, Delete, and Insert methods, as well as a way to “skip” through the data.

Related Post

  • Silverlight, Web Services and DatasetsSilverlight, Web Services and Datasets I sat down today to learn about using Silverlight and Dataset from a Web Service.  Something you’d think would be rather trivial. I mean, seriously folks.  We use Datasets as a means of...
  • Silverlight – DatabindingSilverlight – Databinding When I was learning DataBinding in both .NET 1.0 and .NET 2.0, I quickly discovered that most of what I learned about DataBinding for ASP.NET was useless as I moved to Windows Forms and what I lear...
  • Silverlight – Navigating DataSilverlight – Navigating Data Last week I demonstrated how to access data from a web service in Silverlight and display it on the page.  Today we are going to continue on with that demo and look at how to navigate through...
  • Silverlight – Wire up your form for programmingSilverlight – Wire up your form for programming As I mentioned a couple of weeks ago, learning Silverlight is a lot more about relearning some basic assumptions than it is about learning a new language.  We've already looked at the basic layout ...
  • Installing Silverlight2 Tools for Visual StudioInstalling Silverlight2 Tools for Visual Studio I was talking with a friend of mine a couple of days ago about the future of web development and XAML specifically when he made the comment about the tools not being available for the average deve...