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.
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:
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:
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:
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.
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 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 Book 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 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!
Was this article worth reading? Share it with fellow developers too. Thanks!
Mahesh Sabnis is a DotNetCurry author and a Microsoft MVP having over two decades 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), and Front-end technologies like Angular and React. Follow him on twitter @
maheshdotnet or connect with him on
LinkedIn