Wednesday, September 26, 2012

WCF Service Returns List of Objects to WPF DataGrid

Today we will build WCF service that returns a list of objects, an Employee objects, in our case. And we will build a WPF client application which will show the result in DataGrid.

First, let's create WCF service. Choose WCF Service Application from the list:
Add new project (WCF Service)
Visual Studio will automatically create template project with IService.cs and Service.svc files, where actually all the service logic will be written. I added the Employee class and edited Service.cs and IService.cs in order to service be able to return a list of employees. Let's see:

Employee.cs:
[DataContract]
public class Employee
{
    public Employee(string name, string email, string position, int age)
    {
        Name = name;
        Email = email;
        Position = position;
        Age = age;            
    }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string Email { get; set; }
    [DataMember]
    public string Position { get; set; }
    [DataMember]
    public int Age { get; set; }
}
We must state DataContract attribute on our Employee class because we are going to send employee objects to the client.

IService.cs:
[ServiceContract]
public interface IService
{     
    [OperationContract]
    List<Employee> GetEmployees();     
}
Service.svc.cs:
public class Service : IService
{
    public List<Employee> GetEmployees()
    {
        List<Employee> employees = new List<Employee>();
        employees.Add(new Employee("John", "john@codearsenal.net", "Developer", 32));
        employees.Add(new Employee("Smith", "smith@codearsenal.net", "Service", 45));
        employees.Add(new Employee("Lucas", "lucas@codearsenal.net", "Manager", 25));
        employees.Add(new Employee("Richard", "richard@codearsenal.net", "IT", 31));
        employees.Add(new Employee("Anna", "anna@codearsenal.net", "HR", 28));
        return employees;
    }
}
Ok, the service is ready to send employee list to the client. Now let's create our WPF client that will connect to the service and retrieve the data. Add new WPF project to the solution:

Add New Project - WPF Client

Now we need to add reference to our WCF service:

Add Service Reference

The last is to add some code that will retrieve the data from the service and bind that data to the DataGrid.

ViewModel.cs:

public class ViewModel
{
    WCFServiceReference.ServiceClient _serviceClient = new ServiceClient();        

    public List<Employee> Employees
    {
        get 
        {
            return _serviceClient.GetEmployees().ToList(); 
        }            
    }
}

MainWindow.xaml:
<Grid>
    <DataGrid Name="dataGrid1" ItemsSource="{Binding Employees}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
            <DataGridTextColumn Header="Email" Binding="{Binding Email}" />
            <DataGridTextColumn Header="Position" Binding="{Binding Position}" />
            <DataGridTextColumn Header="Age" Binding="{Binding Age}" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>
This is what we'll see once we build and run the project:
WPF Client window showing result in datagrid

Download the source code (Visual Studio 2010 project).

5 comments:

  1. Do you know how to add a close button and functionality to a TabItem?

    ReplyDelete
    Replies
    1. Hi Michael, here is very elegant solution of what you looking: http://geekswithblogs.net/kobush/archive/2007/04/08/closeabletabitem.aspx

      Delete
    2. Hi,

      I would like to say thanks for your guide, very informative, however, I appear to have a problem : (

      I am hosting the service on a different server and connecting to it with a service reference. Everything in my service works fine and can be accessed by the local application but when following your guide to bind a DataGrid I have hit an issue.

      I have followed the guide word for work and all appears fine until the point of compiling at which point I receive:

      Inconsistent accessibility: property ype 'System.Collections.Generic.List' is less accessible than property 'ConnectBackend.ViewModel.companies'

      Do you know why I am receiving this error when your guide says everything should work. I have also checked everything is definitely set as public.

      Many thanks

      Delete
  2. Hi,

    Thanks for the guide, very helpful, however, I have a problem in using this approach with my WCF service on a different server.

    I host the service which sends out the list of objects correctly (I can confirm this by doing a simple foreach on the results of the web service)

    List companies = client.GetCompanies().ToList();
    StringBuilder sb = new StringBuilder();
    foreach (var item in companies)
    {
    sb.Append(item.CompanyID + " - " + item.CompanyName + " - " + item.CompanyUserCount);
    sb.Append(Environment.NewLine);
    }
    MessageBox.Show(sb.ToString());

    This throws the list back of:

    1 - Comp1 - 10
    2 - Comp2 - 20
    3 - Comp3 - 30
    4 - Comp4 - 40
    5 - Comp5 - 50

    The problem is when I go to set the itemssource of my datagrid to my 'companies' list.

    dg_companies.itemssource = companies;

    When I run the program I get a datagrid that looks like:

    EXTENSIONDATA |
    ------------------------------------------------------------------------
    System.Runtime.Serialization.ExtensionDataObject |
    System.Runtime.Serialization.ExtensionDataObject |
    System.Runtime.Serialization.ExtensionDataObject |
    System.Runtime.Serialization.ExtensionDataObject |
    System.Runtime.Serialization.ExtensionDataObject |

    Do you have any idea why this may be happening?

    Many thanks

    ReplyDelete