Silverlight 4.0 - Using Commanding Feature to Fetch data from a WCF 4.0 service

Posted by: Mahesh Sabnis , on 6/20/2010, in Category Silverlight 2, 3, 4 and 5
Views: 33776
Abstract: Command is a class that supports the ICommand interface and lets you data bind specific operations in your application. In Silverlight 4, there is a new pair of properties added to the ButtonBase and Hyperlink classes named Command and CommandParameter that lets you do so.
I hope most of you have started using Silverlight 4.0. This latest version of Silverlight (SL) is full of new features for building rich media andLine of Business (LOB) applications. If you are new to Silverlight, you can read all about the new features of SL 4.0 from www.silverlight.net, the official SL site. In this article I am going to discuss the new commanding support provided to SL 4.0 applications.     
During one of my recent Silverlight Training, we were discussing communication with Business/Data classes to fetch and update the data and stumbled upon the new Commanding features in SL 4. SL 4.0 commanding provides easy and flexible code-less development mechanism. Command is a class that supports the ICommand interface and lets you data bind specific operations in your application. In Silverlight 4, there is a new pair of properties added to the ButtonBase and Hyperlink classes named Command and CommandParameter that lets you do so. I started working on it and in this article; I will be discussing it with you.
This article is divided into two parts. In the first part, I will show you how to fetch data using the Commanding feature. In the next part (forthcoming article), I will show you how to use Commanding Parameters for performing DML Operations.
In this article I have used WCF 4.0, Silverlight 4.0. [Update] The 2nd part of this article can be viewed over here Silverlight 4: Using Commanding Parameters for Performing Insert Operations
 
Task 1: Creation of WCF 4.0 Service.
 
This service will expose contracts for fetching data and performing DML operations to and from Database.
Step 1: Start VS2010 and Create a blank solution, name this as ‘SILV4_ICommand_Application’.
Step 2: To this solution, add a new WCF Application, name it as ‘WCF_DataService’. In this project, rename ‘IService1.cs’ to ‘IService.cs’. Rename ‘Service1.svc’ to ‘Service.svc’.
Step 3: Right click on ‘Service.Svc’ and Select ‘View Markup’ and change the service attribute vale of @ServiceHost from ‘Service1’ to ‘Service’. The markup will be as shown below:
<%@ ServiceHostLanguage="C#" Debug="true" Service="WCF_DataService.Service" CodeBehind="Service.svc.cs"%>
Step 4: Open IService.cs and write the following DataContract and ServiceContract:
C#
using System.Runtime.Serialization;
using System.ServiceModel;
 
namespace WCF_DataService
{
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        clsEmployee[] GetAllEmployees();
        [OperationContract]
        int InsertEmployee(clsEmployee objEmp);
 
    }
 
    [DataContract]
    public class clsEmployee
    {
        [DataMember]
        public int EmpNo { get; set; }
        [DataMember]
        public string EmpName { get; set; }
        [DataMember]
        public int Salary { get; set; }
        [DataMember]
        public int DeptNo { get; set; }
    }
}
 
 
VB.NET
Namespace WCF_DataService
      <ServiceContract>
      Public Interface IService
            <OperationContract>
            Function GetAllEmployees() As clsEmployee()
            <OperationContract>
            Function InsertEmployee(ByVal objEmp As clsEmployee) As Integer
 
      End Interface
 
      <DataContract>
      Public Class clsEmployee
            <DataMember>
            Public Property EmpNo() As Integer
            <DataMember>
            Public Property EmpName() As String
            <DataMember>
            Public Property Salary() As Integer
            <DataMember>
            Public Property DeptNo() As Integer
      End Class
End Namespace
Step 5: Open ‘Service.Svc.cs’ and Implement the ‘IService’ interface in the ‘Service’ class as below:
C#
using System;
using System.Data;
using System.Data.SqlClient;
 
namespace WCF_DataService
{
    public class Service : IService
    {
        SqlConnection Conn;
        SqlCommand Cmd;
        public Service()
        {
            Conn = new SqlConnection("Data Source=.;Initial Catalog=Company;Integrated Security=SSPI");
        }
 
        public clsEmployee[] GetAllEmployees()
        {
            Conn.Open();
            Cmd = new SqlCommand();
            Cmd.Connection = Conn;
            Cmd.CommandText = "Select * from Employee";
            SqlDataReader Reader = Cmd.ExecuteReader();
            int i = 0;
 
            DataTable DtEmp = new DataTable();
            DtEmp.Load(Reader);
 
            clsEmployee[] arrEmp = new clsEmployee[DtEmp.Rows.Count];
 
            foreach (DataRow Dr in DtEmp.Rows)
            {
                arrEmp[i] = new clsEmployee()
                {
                    EmpNo = Convert.ToInt32(Dr["EmpNo"]),
                    EmpName = Dr["EmpName"].ToString(),
                    Salary = Convert.ToInt32(Dr["Salary"]),
                    DeptNo = Convert.ToInt32(Dr["DeptNo"])
                };
                i++;
            }
            Conn.Close();
            return arrEmp;
        }
 
        public int InsertEmployee(clsEmployee objEmp)
        {
 
            int Res = 0;
            Conn.Open();
            Cmd = new SqlCommand();
            Cmd.Connection = Conn;
 
            Cmd.CommandText = "Insert into Employee Values(@EmpNo,@EmpName,@Salary,@DeptNo)";
 
            Cmd.Parameters.AddWithValue("@EmpNo", objEmp.EmpNo);
            Cmd.Parameters.AddWithValue("@EmpName", objEmp.EmpName);
            Cmd.Parameters.AddWithValue("@Salary", objEmp.Salary);
            Cmd.Parameters.AddWithValue("@DeptNo", objEmp.DeptNo);
 
 
            Res = Cmd.ExecuteNonQuery();
 
            if (Res > 0)
            {
                Res = 1;
            }
 
            Conn.Close();
 
            return Res;
        }
    }
}
 
 
VB.NET
Imports System
Imports System.Data
Imports System.Data.SqlClient
 
Namespace WCF_DataService
      Public Class Service
            Implements IService
            Private Conn As SqlConnection
            Private Cmd As SqlCommand
            Public Sub New()
                  Conn = New SqlConnection("Data Source=.;Initial Catalog=Company;Integrated Security=SSPI")
            End Sub
 
            Public Function GetAllEmployees() As clsEmployee()
                  Conn.Open()
                  Cmd = New SqlCommand()
                  Cmd.Connection = Conn
                  Cmd.CommandText = "Select * from Employee"
                  Dim Reader As SqlDataReader = Cmd.ExecuteReader()
                  Dim i As Integer = 0
 
                  Dim DtEmp As New DataTable()
                  DtEmp.Load(Reader)
 
                  Dim arrEmp(DtEmp.Rows.Count - 1) As clsEmployee
 
                  For Each Dr As DataRow In DtEmp.Rows
                        arrEmp(i) = New clsEmployee() With {.EmpNo = Convert.ToInt32(Dr("EmpNo")), .EmpName = Dr("EmpName").ToString(), .Salary = Convert.ToInt32(Dr("Salary")), .DeptNo = Convert.ToInt32(Dr("DeptNo"))}
                        i += 1
                  Next Dr
                  Conn.Close()
                  Return arrEmp
            End Function
 
            Public Function InsertEmployee(ByVal objEmp As clsEmployee) As Integer
 
                  Dim Res As Integer = 0
                  Conn.Open()
                  Cmd = New SqlCommand()
                  Cmd.Connection = Conn
 
                  Cmd.CommandText = "Insert into Employee Values(@EmpNo,@EmpName,@Salary,@DeptNo)"
 
                  Cmd.Parameters.AddWithValue("@EmpNo", objEmp.EmpNo)
                  Cmd.Parameters.AddWithValue("@EmpName", objEmp.EmpName)
                  Cmd.Parameters.AddWithValue("@Salary", objEmp.Salary)
                  Cmd.Parameters.AddWithValue("@DeptNo", objEmp.DeptNo)
 
 
                  Res = Cmd.ExecuteNonQuery()
 
                  If Res > 0 Then
                        Res = 1
                  End If
 
                  Conn.Close()
 
                  Return Res
            End Function
      End Class
End Namespace
 
Step 6: Since you have selected WCF 4.0, it is not necessary for you to make any changes in Web.Config file because WCF 4.0 sets ‘basicHttpBinding’ by default for WCF 4.0 service. This binding is anyway required for Silverlight client applications.
Step 7: Build the project and make sure that it is error free. You can browse the SVC file by right clicking and selecting ‘View In Browser’ option. It should show the following page:
Service
Step 8: Publish this service on IIS (IIS 7.0 is recommended).
 
Task 2: Creating Silverlight 4.0 Client Application
 
In this step, we will add a new SL 4.0 project. This project will contain classes for Commanding, as well as classes for making call to the WCF service. The XAML code in SL user control will use this new Commanding facility and using these commanding classes, the communication will be made possible with the WCF service.
The ‘ICommand’ interface provided here defines the contract for commanding. This is the input actions made by the user while interacting with UI application e.g. Button Click etc. This interface provides methods like:
1.    CanExecute: Returns Boolean based upon the condition and display the result of the action performed by the end user.
2.    Execute: This method is responsible for handling/executing the business action based upon the result from CanExecute.
Step 1: To the same solution, add a new Silverlight Application project, make sure that, SL 4.0 version is selected. VS2010 by default creates SL 3.0 project.
Step 2: In this project, add the reference of the WCF_DataService, created in Task1.
Step 3: In this project add two classes, ‘AllEmployeeViewModel’ and ‘GetAllEmployeeCommand’ as below:
AllEmployeeViewModel.cs
C#
using System;
using System.Windows.Input;
using System.Collections.ObjectModel;
using Silverlight.Com.View.Client.MyRef;
 
namespace Silverlight.Com.View.Client
{
 
    ///<summary>
    /// The Class Act as a ViewModel class, this makes async call to WCF service and retrieve all Employees.
    ///</summary>
 
    public class AllEmployeeViewModel
    {
        public ObservableCollection<clsEmployee> Employees { get; set; }
 
        ServiceClient Proxy;
 
        public AllEmployeeViewModel()
        {
            Employees = new ObservableCollection<clsEmployee>();
            Proxy = new ServiceClient();
        }
 
        public ICommand GetEmployees
        {
            get
            {
                return new GetAllEmployeeCommand(this);
            }
        }
 
        public void GetAllEmployees()
        {
            Proxy.GetAllEmployeesCompleted += new EventHandler<GetAllEmployeesCompletedEventArgs>(Proxy_GetAllEmployeesCompleted);
            Proxy.GetAllEmployeesAsync();
        }
 
        void Proxy_GetAllEmployeesCompleted(object sender, GetAllEmployeesCompletedEventArgs e)
        {
            if (e.Result != null)
            {
                foreach (clsEmployee Emp in e.Result)
                {
                    Employees.Add(Emp);
                }
            }
        }
 
    }
}
 
 
 
VB.NET
Imports System
Imports System.Windows.Input
Imports System.Collections.ObjectModel
Imports Silverlight.Com.View.Client.MyRef
 
Namespace Silverlight.Com.View.Client
 
      ''' <summary>
      ''' The Class Act as a ViewModel class, this makes async call to WCF service and retrieve all Employees.
      ''' </summary>
 
      Public Class AllEmployeeViewModel
            Public Property Employees() As ObservableCollection(Of clsEmployee)
 
            Private Proxy As ServiceClient
 
            Public Sub New()
                  Employees = New ObservableCollection(Of clsEmployee)()
                  Proxy = New ServiceClient()
            End Sub
 
            Public ReadOnly Property GetEmployees() As ICommand
                  Get
                        Return New GetAllEmployeeCommand(Me)
                  End Get
            End Property
 
            Public Sub GetAllEmployees()
                  AddHandler Proxy.GetAllEmployeesCompleted, AddressOf Proxy_GetAllEmployeesCompleted
                  Proxy.GetAllEmployeesAsync()
            End Sub
 
            Private Sub Proxy_GetAllEmployeesCompleted(ByVal sender As Object, ByVal e As GetAllEmployeesCompletedEventArgs)
                  If e.Result IsNot Nothing Then
                        For Each Emp As clsEmployee In e.Result
                              Employees.Add(Emp)
                        Next Emp
                  End If
            End Sub
 
      End Class
End Namespace
 
 
The above class is responsible for making an async call to WCF service and returning result. The class exposes public property of the type ‘ICommand’ which is responsible for communicating with XAML using Command class as shown below:
GetAllEmployeeCommand.cs
C#
using System;
using System.Windows.Input;
 
 
namespace Silverlight.Com.View.Client
{
    ///<summary>
    /// The Following Class is used to Define The Actions to be performed by the UI.
    /// This Defines the Contract between the Model and UI.
    ///</summary>
 
    public class GetAllEmployeeCommand : ICommand
    {
 
        AllEmployeeViewModel EmployeeViewModel;
 
        public GetAllEmployeeCommand(AllEmployeeViewModel empViewModel)
        {
            EmployeeViewModel = empViewModel;
        }
 
 
        public bool CanExecute(object parameter)
        {
 
            bool action = false;
 
            //Check wheather the Data is retrived or not
 
            if (EmployeeViewModel.Employees.Count >= 0)
            {
                action = true;
            }
            return action;
        }
 
        public event EventHandler CanExecuteChanged;
 
        public void Execute(object parameter)
        {
            //Make Call to ViewModel Class for retriving the Employees
 
            EmployeeViewModel.GetAllEmployees();
        }
    }
}
 
 
VB.NET
Imports System
Imports System.Windows.Input
 
 
Namespace Silverlight.Com.View.Client
      ''' <summary>
      ''' The Following Class is used to Define The Actions to be performed by the UI.
      ''' This Defines the Contract between the Model and UI.
      ''' </summary>
 
      Public Class GetAllEmployeeCommand
            Implements ICommand
 
            Private EmployeeViewModel As AllEmployeeViewModel
 
            Public Sub New(ByVal empViewModel As AllEmployeeViewModel)
                  EmployeeViewModel = empViewModel
            End Sub
 
 
            Public Function CanExecute(ByVal parameter As Object) As Boolean Implements ICommand.CanExecute
 
                  Dim action As Boolean = False
 
                  'Check wheather the Data is retrived or not
 
                  If EmployeeViewModel.Employees.Count >= 0 Then
                        action = True
                  End If
                  Return action
            End Function
 
            Public Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
 
            Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute
                  'Make Call to ViewModel Class for retriving the Employees
 
                  EmployeeViewModel.GetAllEmployees()
            End Sub
      End Class
End Namespace
 
The class is responsible for making call to the Business action using ‘Execute’ method. The CanExecute() method here checks count of the employee collection. Only if it is more than or equal to zero, an action performed by the end user will be completed. 
Step 4: In the SL project, add a new Silverlight UserControl > name it as ‘AllEmployeeView.Xaml’. On this user control, drag-drop a datagrid and a button.
Step 5: Now since we need to make call to the ‘AllEmployeeviewModel’ class, register the namespace of this class in the Xaml as shown below:
xmlns:src="clr-namespace:Silverlight.Com.View.Client"
Step 6: Instantiate the ‘AllEmployeeViewModel’ class in the Xaml as shown below:
<UserControl.Resources>
 <src:AllEmployeeViewModelx:Key="empKey"></src:AllEmployeeViewModel>
</UserControl.Resources>
 
The above declaration will make calls to the constructor of the ‘AllEmployeeViewModel’ class. The constructor defines ‘ObservableCollection’ for Employees as well as the Proxy object for the WCF service.
Step 7: To bind the observable collection to the Datagrid as well as the button control on the User Control, change the XAML as shown below: (Marked in italics)
<Gridx:Name="MainGrid"Background="White"Width="400"
 Height="407" DataContext="{Binding Source={StaticResourceempKey}}">
 
 <Gridx:Name="grdAllEmp" DataContext="{Binding Path=Employees}">
 
    <sdk:DataGridAutoGenerateColumns="True"Height="274"
    HorizontalAlignment="Left"Margin="8,8,0,0"
     Name="dgEmployee" VerticalAlignment="Top"Width="385"
    ItemsSource="{Binding}"/>
 
    <ButtonContent="Get All Employees"Height="23"
    HorizontalAlignment="Left"Margin="12,288,0,0"
     Name="btnAllEmplloyees"VerticalAlignment="Top"Width="381"
    Command="{Binding Path=DataContext.GetEmployees,ElementName=MainGrid}"/>
 </Grid>
</Grid>
 
The parent Grid ‘MainGrid’ is bound with an instance of the ‘AllEmployeeViewModel’ instance. This instance exposes Employee collection through constructor of the class. The first child grid ‘grdAllEmp’ binds with ‘Employee’. This is an actual ObservableCollection returned from WCF service. To fetch the data by making call to WCF service, the method ‘GetAllEmployees()’ must be called from the ‘AllEmployeeViewModel’ class. For the purpose of method call, we will now use Commanding feature of the SL 4.0. Use ‘Command’ property of the button element and bind it with ‘GetEmployees’ public property of the ‘AllEmployeeViewModel’ class as shown in above XAML code. This property returns the object of ‘GetAllEmployeeCommand’ class. This class defines an execution for the ‘GetAllEmployees()’ method. By doing this step now, Button click action will directly call the method from the business class and fetch the data.
Step 8: Open MainPage.Xaml and drag-drop a button on it. Name this as ‘btnAllEmployee’. On the click event of this button write the following code:
C#
private void btnAllEmployees_Click(object sender, RoutedEventArgs e)
{
    AllEmployeesView objAllEmpView = new AllEmployeesView();
    grdAllEmp.Children.Add(objAllEmpView);
}
 
VB.NET
Private Sub btnAllEmployees_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
      Dim objAllEmpView As New AllEmployeesView()
      grdAllEmp.Children.Add(objAllEmpView)
End Sub
 
The above code creates an object of the ‘AllEmployeeView’ and displays it.
Step 9: Run the application, click on the button and the ‘AllEmployeeView’ will be displayed as below:
AllEmployees
The button ‘Get All Employees’ will be enabled only if the CanExecute() method returns true. Click on the ‘Get All Employees’ button and the following result will be displayed:
AllEmployees_Details
In the next article, we will use the Commanding Parameters for performing DML Operations.  [Update] The 2nd part of this article can be viewed over here Silverlight 4: Using Commanding Parameters for Performing Insert Operations
Conclusion: Silverlight 4.0 commanding provides easy and flexible code-less development mechanism. No compiled code is required for handling Xaml elements on the View. If you isolate command classes and business action classes in separate layers, then each layer can be tested separately, so there is absolutely no dependency between these layers.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce the The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this eBook aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and the C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Mahesh Sabnis is a DotNetCurry author and Microsoft MVP having over 17 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). Follow him on twitter @maheshdotnet


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Shailendra Sute on Wednesday, June 23, 2010 5:21 AM
In the button click event we have created instance of "AllEmployeesView" class. What is this class?
Comment posted by Simon on Thursday, December 16, 2010 1:41 AM
I must have looked at 20 different tutorials before I found this one. Thank you so much for your clear and concise example.
Comment posted by Vivek Ahlawat on Tuesday, March 27, 2012 5:51 AM
At the 2 step...Step 2: In this project, add the reference of the WCF_DataService, created in Task1.
I am not able to add the reference of the WCF...Please give me rply ASAP..

Categories

JOIN OUR COMMUNITY

POPULAR ARTICLES

C# .NET BOOK

C# Book for Building Concepts and Interviews

Tags

JQUERY COOKBOOK

jQuery CookBook