Silverlight 4.0 has several new features and it has been listed down well over here. One of the most exciting features of Silverlight 4.0, is its capability for building Line-of-Business (LOB) applications. Last week I was conducting a training program for one of my client on VS 2010, where I was asked lots of queries regarding Silverlight 4.0 and its capabilities as compare of its earlier versions. In this article, I will discuss one of the questions on Data Validation in Silverlight 4.0.
In this article, I have used ‘IDataErrorInfo’ interface which is newly provided in Silverlight 4.0 under System.ComponentModel namepsace. This interface needs to be implemented by the data entity class which helps in defining custom validations for data to be entered using Silverlight 4.0 UI controls.
Defining Data Entity class and implementing ‘IDataErrorInfo’
Step 1: Open VS2010 and create a new Silverlight 4.0 Application. Name it as ‘SILV4_DataValidationFeatures’.
Step 2: To this project, add a new class file and name it as ‘ApplicationClass’.
Step 3: In this class file, add the following class and name it as ‘Employee’ as below.
C#
public class Employee : INotifyPropertyChanged, IDataErrorInfo
{
int _EmpNo;
public int EmpNo
{
get
{
return _EmpNo;
}
set
{
_EmpNo = value;
ChangeValue("EmpNo");
}
}
string _EmpName;
public string EmpName
{
get
{
return _EmpName;
}
set
{
_EmpName = value;
ChangeValue("EmpName");
}
}
int _Salary;
public int Salary
{
get
{
return _Salary;
}
set
{
_Salary = value;
ChangeValue("Salary");
}
}
int _DeptNo;
public int DeptNo
{
get
{
return _DeptNo;
}
set
{
_DeptNo = value;
ChangeValue("DeptNo");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void ChangeValue(string PropName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(PropName));
}
}
string err;
public string Error
{
get { return err; }
}
public string this[string columnName]
{
get
{
string msg = null;
if (columnName == "EmpNo")
{
if (EmpNo <= 0 || EmpNo.ToString().Length > 5)
{
msg = "EmpNo must not be Negative or Lenght must not be more than 5.";
}
}
if (columnName == "EmpName")
{
if (EmpName.Equals(string.Empty))
{
msg = "EmpName is must,Please enter Correct Value.";
}
}
if (columnName == "Salary")
{
if (Salary <= 0)
{
msg = "Salary must not be Negative.";
}
}
if (columnName == "DeptNo")
{
if (DeptNo <= 0)
{
msg = "DeptNo must not be Negative.";
}
}
return msg;
}
}
}
VB.NET
Public Class Employee
Implements INotifyPropertyChanged, IDataErrorInfo
Private _EmpNo As Integer
Public Property EmpNo() As Integer
Get
Return _EmpNo
End Get
Set(ByVal value As Integer)
_EmpNo = value
ChangeValue("EmpNo")
End Set
End Property
Private _EmpName As String
Public Property EmpName() As String
Get
Return _EmpName
End Get
Set(ByVal value As String)
_EmpName = value
ChangeValue("EmpName")
End Set
End Property
Private _Salary As Integer
Public Property Salary() As Integer
Get
Return _Salary
End Get
Set(ByVal value As Integer)
_Salary = value
ChangeValue("Salary")
End Set
End Property
Private _DeptNo As Integer
Public Property DeptNo() As Integer
Get
Return _DeptNo
End Get
Set(ByVal value As Integer)
_DeptNo = value
ChangeValue("DeptNo")
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler
Public Sub ChangeValue(ByVal PropName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(PropName))
End Sub
Private err As String
Public ReadOnly Property [Error]() As String
Get
Return err
End Get
End Property
Default Public ReadOnly Property Item(ByVal columnName As String) As String
Get
Dim msg As String = Nothing
If columnName = "EmpNo" Then
If EmpNo <= 0 OrElse EmpNo.ToString().Length > 5 Then
msg = "EmpNo must not be Negative or Lenght must not be more than 5."
End If
End If
If columnName = "EmpName" Then
If EmpName.Equals(String.Empty) Then
msg = "EmpName is must,Please enter Correct Value."
End If
End If
If columnName = "Salary" Then
If Salary <= 0 Then
msg = "Salary must not be Negative."
End If
End If
If columnName = "DeptNo" Then
If DeptNo <= 0 Then
msg = "DeptNo must not be Negative."
End If
End If
Return msg
End Get
End Property
}
The Employee class implements ‘IDataErrorInfo’ interface. This provide property ‘Error’ and an indexer which takes property name for custom validation. In the indexer, I have written my own validation error messages.
Step 4: In the class file added in the previous steps, write the following data storage class:
C#
public class EmployeeCollection
{
public ObservableCollection<Employee> ColEmployee { get; set; }
public EmployeeCollection()
{
ColEmployee = new ObservableCollection<Employee>();
ColEmployee.Add(new Employee() { EmpNo = 101, EmpName = "Mahesh", Salary = 76000, DeptNo = 10 });
ColEmployee.Add(new Employee() { EmpNo = 102, EmpName = "Amey", Salary = 66000, DeptNo = 20 });
ColEmployee.Add(new Employee() { EmpNo = 103, EmpName = "Rajesh", Salary = 56000, DeptNo = 10 });
ColEmployee.Add(new Employee() { EmpNo = 104, EmpName = "Rahul", Salary = 77000, DeptNo = 20 });
ColEmployee.Add(new Employee() { EmpNo = 105, EmpName = "Ajay", Salary = 79000, DeptNo = 30 });
ColEmployee.Add(new Employee() { EmpNo = 106, EmpName = "Pradnya", Salary = 86000, DeptNo = 10 });
}
}
VB.NET
Public Class EmployeeCollection
Public Property ColEmployee() As ObservableCollection(Of Employee)
Public Sub New()
ColEmployee = New ObservableCollection(Of Employee)()
ColEmployee.Add(New Employee() With {.EmpNo = 101, .EmpName = "Mahesh", .Salary = 76000, .DeptNo = 10})
ColEmployee.Add(New Employee() With {.EmpNo = 102, .EmpName = "Amey", .Salary = 66000, .DeptNo = 20})
ColEmployee.Add(New Employee() With {.EmpNo = 103, .EmpName = "Rajesh", .Salary = 56000, .DeptNo = 10})
ColEmployee.Add(New Employee() With {.EmpNo = 104, .EmpName = "Rahul", .Salary = 77000, .DeptNo = 20})
ColEmployee.Add(New Employee() With {.EmpNo = 105, .EmpName = "Ajay", .Salary = 79000, .DeptNo = 30})
ColEmployee.Add(New Employee() With {.EmpNo = 106, .EmpName = "Pradnya", .Salary = 86000, .DeptNo = 10})
End Sub
End Class
Creating Silverlight 4.0 UI
Step 1: Open MainPage.Xaml and write the following Xaml for generating UI:
<UserControl x:Class="SILV4_DatavalidationFeatures.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:src="clr-namespace:SILV4_DatavalidationFeatures"
mc:Ignorable="d"
d:DesignHeight="322" d:DesignWidth="668"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<UserControl.Resources>
<src:EmployeeCollection x:Key="EmpDs"></src:EmployeeCollection>
<Style TargetType="TextBlock">
<Setter Property="Width" Value="100"></Setter>
<Setter Property="Foreground" Value="Black"></Setter>
<Setter Property="Height" Value="50"></Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White" Height="320" Width="667"
DataContext="{Binding Path=ColEmployee, Source={StaticResource EmpDs}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="303*" />
<ColumnDefinition Width="364*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="270"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Height="45" HorizontalAlignment="Left" Margin="175,9,0,0"
Name="textBlock1" Text="Employee Information System"
VerticalAlignment="Top" Width="402" TextAlignment="Center"
FontSize="22" Foreground="#FFB10000" FontWeight="ExtraBold"
Grid.ColumnSpan="2" Grid.RowSpan="2" />
<Grid Grid.Row="1" Grid.Column="0" Name="grdRecord">
<TextBlock Grid.Row="1" Height="23" HorizontalAlignment="Left"
Margin="12,21,0,0" Name="textBlock2" Text="EmpNo"
VerticalAlignment="Top" Width="100" />
<TextBlock Grid.Row="1" Height="23"
HorizontalAlignment="Left" Margin="12,70,0,0"
Name="textBlock3" Text="EmpName"
VerticalAlignment="Top" Width="100" />
<TextBlock Grid.Row="1" Height="23"
HorizontalAlignment="Left" Margin="12,117,0,0"
Name="textBlock4" Text="Salary"
VerticalAlignment="Top" Width="100" />
<TextBlock Grid.Row="1" Height="23"
HorizontalAlignment="Left" Margin="12,160,0,0" Name="textBlock5"
Text="DeptNo" VerticalAlignment="Top" Width="100" />
<TextBox Grid.Row="1" Height="23"
HorizontalAlignment="Left" Margin="148,21,0,0"
Name="txtEno"
Text="{Binding Path=EmpNo,Mode=TwoWay,ValidatesOnDataErrors=True}"
VerticalAlignment="Top" Width="120" />
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left"
Margin="148,66,0,0" Name="txtEname"
Text="{Binding Path=EmpName,Mode=TwoWay,ValidatesOnDataErrors=True}"
VerticalAlignment="Top" Width="120"
/>
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left"
Margin="148,117,0,0" Name="txtSalary"
Text="{Binding Path=Salary,Mode=TwoWay,ValidatesOnDataErrors=True,StringFormat=C}"
VerticalAlignment="Top" Width="120" />
<TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left"
Margin="148,160,0,0" Name="txtDno"
Text="{Binding Path=DeptNo,Mode=TwoWay,ValidatesOnDataErrors=True}"
VerticalAlignment="Top" Width="120" />
<Button Content="Add" Height="23" HorizontalAlignment="Left"
Margin="55,233,0,0" Name="btnAdd" VerticalAlignment="Top"
Width="133" Click="btnAdd_Click" />
</Grid>
<sdk:DataGrid AutoGenerateColumns="False"
Grid.Column="1" Grid.Row="1"
Height="243" HorizontalAlignment="Left" Margin="11,10,0,0"
Name="dgEmp" VerticalAlignment="Top" Width="340"
ItemsSource="{Binding}">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Binding="{Binding EmpNo}"
Width="80" Header="EmpNo"></sdk:DataGridTextColumn>
<sdk:DataGridTextColumn Binding="{Binding EmpName}"
Width="120" Header="EmpName"></sdk:DataGridTextColumn>
<sdk:DataGridTextColumn Binding="{Binding Salary}"
Width="80" Header="Salary"></sdk:DataGridTextColumn>
<sdk:DataGridTextColumn Binding="{Binding DeptNo}"
Width="80" Header="DeptNo"></sdk:DataGridTextColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
</UserControl>
In the above xaml, the code marked in ‘Green’ represents the import of the namespace and the declaration an object of the ‘EmployeeCollection’ data store class. The code which is marked by ‘Yellow’ represents how properties from data entity class ‘Employee’ are bound with textboxes and data validation mode. This automatically invalidates the control when user enters invalidate input value. Since the ‘Employee’ class implements ‘IDataErrorInfo’, and its object is bound with textbox, the values entered in textbox will be delivered on the employee object to the concern property. This further verifies value against the code in the indexer. If the value is invalid, then the control shows a ‘Red’ outline and the notification as a tip.
Step 2: Open MainPage.Xaml.cs and write the following code in various events:
C#
Employee objEmp;
EmployeeCollection objCol;
public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
objEmp = new Employee();
objCol = new EmployeeCollection();
objEmp = (from emp in objCol.ColEmployee
select new Employee()
{
EmpNo = emp.EmpNo,
EmpName = emp.EmpName,
DeptNo = emp.DeptNo,
Salary = emp.Salary
}).First() ;
this.DataContext = this;
grdRecord.DataContext = objEmp;
}
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
if (Validation.GetHasError(txtEno) || Validation.GetHasError(txtEname)
|| Validation.GetHasError(txtSalary) || Validation.GetHasError(txtDno))
{
MessageBox.Show("Please satisfy the Validation Condition");
}
else
{
objCol.ColEmployee.Add(objEmp);
dgEmp.DataContext = objCol.ColEmployee;
}
}
VB.NET
Private objEmp As Employee
Private objCol As EmployeeCollection
Public Sub New()
InitializeComponent()
AddHandler Loaded, AddressOf MainPage_Loaded
End Sub
Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
objEmp = New Employee()
objCol = New EmployeeCollection()
objEmp = (
From emp In objCol.ColEmployee
Select New Employee() With {.EmpNo = emp.EmpNo, .EmpName = emp.EmpName, .DeptNo = emp.DeptNo, .Salary = emp.Salary}).First()
Me.DataContext = Me
grdRecord.DataContext = objEmp
End Sub
Private Sub btnAdd_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
If Validation.GetHasError(txtEno) OrElse Validation.GetHasError(txtEname) OrElse Validation.GetHasError(txtSalary) OrElse Validation.GetHasError(txtDno) Then
MessageBox.Show("Please satisfy the Validation Condition")
Else
objCol.ColEmployee.Add(objEmp)
dgEmp.DataContext = objCol.ColEmployee
End If
End Sub
In the above code, the loaded event queries to the ‘EmployeeCollection’ class and fetches the first record. This is then bound with the textboxes using the yellow marked statement we saw a short while ago. The Add Button click event here checks the validation on every textbox; if the value is invalid then the message displayed else the record will be added in the collection which will be shown in the datagrid.
Step 3: Run the application and try to insert some invalid values, e.g. put negative value for EmpNo the following result will be displayed:
The error tip shows the custom validation information which you have written in the ‘Employee’ data entity class.
Conclusion: Silverlight 4.0, now helps us to build LOB applications using such custom validation mechanism, whenever we need to work on some DML operations.
The entire source code of this article can be downloaded over here
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