Your message has been sent.
This article has been saved to your account.
Go to my account
This article has been emailed to your Kindle.
Send this article
Complete the form below to send this article, Data Validation in Silverlight 4, to a friend (or to yourself). We will never share your details (or your friend's) with anyone. For more information, read our Privacy Policy.
Packt are due to launch a new Enterprise brand, into which future Silverlight titles will be published. For more information on that launch, look here.
In this article by Frank LaVigne, author of Microsoft Silverlight 4 Business Application Development, we shall:
- Bind the data from a data object to Silverlight controls
- Validate data and display feedback to the user
With Silverlight, data validation has been fully implemented, allowing controls to be bound to data objects and those data objects to handle the validation of data and provide feedback to the controls via the Visual State Machine.
The Visual State Machine is a feature of Silverlight used to render to views of a control based on its state. For instance, the mouse over state of a button can actually change the color of the button, show or hide parts of the control, and so on.
Controls that participate in data validation contain a ValidationStates group that includes a Valid, InvalidUnfocused, and InvalidFocused states. We can implement custom styles for these states to provide visual feedback to the user.
Data object
In order to take advantage of the data validation in Silverlight, we need to create a data object or client side business object that can handle the validation of data.
Time for action – creating a data object
We are going to create a data object that we will bind to our input form to provide validation. Silverlight can bind to any properties of an object, but for validation we need to do two way binding, for which we need both a get and a set accessor for each of our properties. In order to use two way binding, we will need to implement the INotifyPropertyChanged interface that defines a PropertyChanged event that Silverlight will use to update the binding when a property changes.
- Firstly, we will need to switch over to Visual Studio and add a new class named CustomerInfo to the Silverlight project:
- Replace the body of the CustomerInfo.cs file with the following code:

using System;
using System.ComponentModel;
namespace CakeORamaData
{
public class CustomerInfo : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged =
delegate { };
private string _cutomerName = null;
public string CustomerName
{
get { return _cutomerName; }
set
{
if (value == _cutomerName)
return;
_cutomerName = value;
OnPropertyChanged("CustomerName");
}
}
private string _phoneNumber = null;
public string PhoneNumber
{
get { return _phoneNumber; }
set
{
if (value == _phoneNumber)
return;
_phoneNumber = value;
OnPropertyChanged("PhoneNumber");
}
}
private string _email = null;
public string Email
{
get { return _email; }
set
{
if (value == _email)
return;
_email = value;
OnPropertyChanged("Email");
}
}
private DateTime _eventDate = DateTime.Now.AddDays(7);
public DateTime EventDate
{
get { return _eventDate; }
set
{
if (value == _eventDate)
return;
_eventDate = value;
OnPropertyChanged("EventDate");
}
}
private void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs
(propertyName));
}
}
}
Code Snippets
Code snippets are a convenient way to stub out repetitive code and increase productivity, by removing the need to type a bunch of the same syntax over and over.
The following is a code snippet used to create properties that execute the OnPropertyChanged method and can be very useful when implementing properties on a class that implements the INotifyPropertyChanged interface.
To use the snippet, save the file as propnotify.snippet to your hard drive.
In Visual Studio go to Tools | Code Snippets Manager (Ctrl + K, Ctrl + B) and click the Import button. Find the propnotify.snippet file and click Open, this will add the snippet.
To use the snippet in code, simply type propnotify and hit the Tab key; a property will be stubbed out allowing you to change the name and type of the property.
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/
VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>propnotify</Title>
<Shortcut>propnotify</Shortcut>
<Description>Code snippet for a property that raises
the PropertyChanged event in a class.</Description>
<Author>Cameron Albert</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<ToolTip>Property type</ToolTip>
<Default>int</Default>
</Literal>
<Literal>
<ID>property</ID>
<ToolTip>Property name</ToolTip>
<Default>MyProperty</Default>
</Literal>
<Literal>
<ID>field</ID>
<ToolTip>Private field</ToolTip>
<Default>_myProperty</Default>
</Literal>
<Literal>
<ID>defaultValue</ID>
<ToolTip>Default Value</ToolTip>
<Default>null</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[private $type$ $field$ = $defaultValue$;
public $type$ $property$
{
get { return $field$; }
set
{
if (value == $field$)
return;
$field$ = value;
OnPropertyChanged("$property$");
}
}
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
What just happened?
We created a data object or client-side business object that we can use to bind to our input controls.
We implemented the INotifyPropertyChanged interface, so that our data object can raise the PropertyChanged event whenever the value of one of its properties is changed. We also defined a default delegate value for the PropertyChanged event to prevent us from having to do a null check when raising the event. Not to mention we have a nice snippet for stubbing out properties that raise the PropertyChanged event.
Now we will be able to bind this object to Silverlight input controls and the controls can cause the object values to be updated so that we can provide data validation from within our data object, rather than having to include validation logic in our user interface code.
Data binding
We are going to bind our CustomerInfo object to our data entry form, using Blend. Be sure to build the solution before switching back over to Blend.
- With MainPage.xaml open in Blend, select the LayoutRoot control. In the Properties panel enter DataContext in the search field and click the New button:
- In the dialog that opens, select the CustomerInfo class and click OK:
- Blend will set the DataContext of the LayoutRoot to an instance of a CustomerInfo class:
- Blend inserts a namespace to our class; set the Grid.DataContext in the XAML of MainPage.xaml:
- Now we will bind the value of CustomerName to our customerName textbox. Select the customerName textbox and then on the Properties panel enter Text in the search field. Click on the Advanced property options icon, which will open a context menu for choosing an option:
- Click on the Data Binding option to open the Create Data Binding dialog:
- In the Create Data Binding dialog (on the Explicit Data Context tab), click the arrow next to the CustomerInfo entry in the Fields list and select CustomerName:
- At the bottom of the Create Data Binding dialog, click on the Show advanced properties arrow to expand the dialog and display additional binding options:
- Ensure that TwoWay is selected in the Binding direction option and that Update source when is set to Explicit. This creates a two-way binding, meaning that when the value of the Text property of the textbox changes the underlying property, bound to Text will also be updated. In our case the customerName property of the CustomerInfo class:
- Click OK to close the dialog; we can now see that Blend indicates that this property is bound by the yellow border around the property input field:
- Repeat this process for both the phoneNumber and emailAddress textbox controls, to bind the Text property to the PhoneNumber and Email properties of the CustomerInfo class. You will see that Blend has modified our XAML using the Binding Expression:
- In the Binding Expression code the Binding is using the CustomerName property as the binding Path. The Path (Path=CustomerName) attribute can be omitted since the Binding class constructor accepts the path as an argument.
- The UpdateSourceTrigger is set to Explicit, which causes any changes in the underlying data object to force a re-bind of the control.
- For the eventDate control, enter SelectedDate into the Properties panel search field and following the same process of data binding, select the EventDate property of the CustomerInfo class. Remember to ensure that TwoWay/Explict binding is selected in the advanced options:



xmlns:local="clr-namespace:CakeORamaData"
<Grid.DataContext>
<local:CustomerInfo/>
</Grid.DataContext>






<TextBox x:Name="customerName" Margin="94,8,8,0" Text="{Binding
CustomerName, Mode=TwoWay, UpdateSourceTrigger=Explicit}"
TextWrapping="Wrap" VerticalAlignment="Top" Grid.Column="1" Grid.
Row="1" MaxLength="40"/>

What just happened?
We utilized Silverlight data binding to bind our input controls to properties of our CustomerInfo class. In the process, we setup the binding to be two way, allowing the controls to set the property values of the CustomerInfo class, thus removing the need to add a bunch of text changed event handlers to manually do it ourselves, saving us more time in development.
We also had a chance to see how much time using Blend can save and how easy it is to add data bindings to controls. We saw the Binding Expression syntax used to define a Binding in XAML and also how to setup a Binding so that changes to the underlying object cause the control to re-bind the value.
Validation
Before we submit information to the server using our WCF service, we need to validate the data input from the user and provide feedback to the user if invalid information is supplied.
Silverlight can report a validation error in one of three scenarios:
- Exceptions thrown from the binding type converter
- Exceptions thrown from the binding object's set accessor
- Exceptions thrown from one of the validation attributes found in the DataAnnotations assembly
We will focus on the set accessor method as this provides the simplest way to get our data validated.
Time for action – validating data input
We will make use of some additional properties of Binding to allow the controls to display the validation states. Blend does not provide a visual way for us to add these additional properties so we have to do it manually in XAML.
- Switch to the XAML view of the MainPage.xaml in Blend and scroll down to where our textbox controls are located.
- Within the Binding Expression (between the { and } of the Binding), add the following two attributes to each one of the bindings on our input controls:
- The NotifyOnValidationError and ValidatesOnException will both cause the control to display an error message if a validation or exception error occurs when the value of the bound property changes.
- Now we need to modify our data object to provide validation in the set accessor of each property. Change the CustomerInfo.cs file to implement our property validation:
- Open the MainPage.xaml.cs file and in the constructor add the following code to set the LayoutRoot.DataContext with a new instance of CustomerInfo:
- Also within the MainPage.xaml file in the submitButton_Click event handler, we will add code to force validation of our data object:
- In Visual Studio, choose Debug | Start without Debugging from the file menu. We are not going to debug because our properties throw exceptions and we just want to see the result. Just click the Submit button and all the textbox controls will highlight with red borders:
- If you hover over the small arrow in the top-right corner of the textbox you will see the error message from the data object:
{Binding CustomerName, Mode=TwoWay, UpdateSourceTrigger=Explicit,
NotifyOnValidationError=True, ValidatesOnExceptions=True }
using System;
using System.ComponentModel;
using System.Text.RegularExpressions;
namespace CakeORamaData
{
public class CustomerInfo : INotifyPropertyChanged
{
private static Regex RegexPhoneNumber = new Regex(@"((\
(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", RegexOptions.Multiline);
private static Regex RegexEmail = new Regex(@"^([\w\-
\.]+)@((\[([0-9]{1,3}\.){3}[0-9]{1,3}\])|(([\w\-]+\.)+)([a-zA-
Z]{2,4}))$", RegexOptions.Multiline | RegexOptions.IgnoreCase);
public event PropertyChangedEventHandler PropertyChanged =
delegate { };
private string _cutomerName = null;
public string CustomerName
{
get { return _cutomerName; }
set
{
if (value == _cutomerName)
return;
if (String.IsNullOrEmpty(value))
throw new ArgumentException("Customer Name is
required.");
if (value.Length < 3 || value.Length > 40)
throw new ArgumentException("Customer Name must be at
least 3 characters and not more than 40 characters
in length.");
_cutomerName = value;
OnPropertyChanged("CustomerName");
}
}
private string _phoneNumber = null;
public string PhoneNumber
{
get { return _phoneNumber; }
set
{
if (value == _phoneNumber)
return;
if (String.IsNullOrEmpty(value))
throw new ArgumentException("Phone Number is
required.");
if (!RegexPhoneNumber.IsMatch(value))
throw new ArgumentException("A valid phone number in the
format (XXX) XXX-XXXX or XXX-XXX-XXXX is required.");
_phoneNumber = value;
OnPropertyChanged("PhoneNumber");
}
}
private string _email = null;
public string Email
{
get { return _email; }
set
{
if (value == _email)
return;
if (String.IsNullOrEmpty(value))
throw new ArgumentException("Email Address is
required.");
if (!RegexEmail.IsMatch(value))
throw new ArgumentException("A valid email address is
required.");
_email = value;
OnPropertyChanged("Email");
}
}
private DateTime _eventDate = DateTime.Now.AddDays(7);
public DateTime EventDate
{
get { return _eventDate; }
set
{
if (value == _eventDate)
return;
_eventDate = value;
OnPropertyChanged("EventDate");
}
}
private void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs
(propertyName));
}
}
}
public MainPage()
{
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
InitializeComponent();
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
LayoutRoot.DataContext = new CustomerInfo();
}
private void submitButton_Click(object sender, System.Windows.
RoutedEventArgs e)
{
var bindingExpression = customerName.GetBindingExpression(TextBo
x.TextProperty);
bindingExpression.UpdateSource();
bindingExpression = phoneNumber.GetBindingExpression(TextBox.
TextProperty);
bindingExpression.UpdateSource();
bindingExpression = emailAddress.GetBindingExpression(TextBox.
TextProperty);
bindingExpression.UpdateSource();
}


What just happened?
We implemented simple data validation in our objects and let the built in Silverlight binding process handle the rest by including some additional attributes in the Binding Expression. We implemented the INotifyPropertyChanged interface in our data object so that the data will be re-bound whenever the values are changed. We also made use of regular expressions to ensure that the phone number and email address are in a valid format.
Summary
In this article, we discussed the following:
- How to create a data object for use with binding
- How to bind data from a data object to Silverlight controls
- How to provide input validation using the built-in validation states
If you have read this article you may be interested to view :
- Navigation Widgets and Styles in Microsoft Silverlight 4
- Understanding Expression Blend and How to Use it with Silverlight 4
- Control templates, Visual State Manager, and Event Handlers in Silverlight 4
- Animation in Silverlight 4
- Creating a WCF Service, Business Object and Data Submission with Silverlight 4
- Creating Data Forms in Silverlight 4
About the Author :
Frank LaVigne
Frank LaVigne has been hooked on software development since he was 12, when he got his own Commodore 64 computer. Since then, he's worked as developer for fi nancial fi rms on Wall Street and also in Europe. He has worked on various Tablet PC soluti ons and on building advanced user experiences in Silverlight and WPF. He lives in the suburbs of Washington, DC. He founded the CapArea.NET User Group Silverlight Special Interest Group and has been recognized by Microsoft as a Tablet PC MVP. He blogs regularly at www.FranksWorld.com.
Books From Packt
|
|



Post new comment