Using Data Annotations to Customize Data Classes
When you use data classes (also known as entity classes) in your Silverlight application, you can apply attributes to the class or members that specify validation rules, specify how the data is displayed, and set relationships between classes. The System.ComponentModel.DataAnnotations namespace contains the classes that are used as data attributes. By applying these attributes on the data class or member, you centralize the data definition and do not have to re-apply the same rules in multiple places.
The data annotation attributes fall into three categories: validation attributes, display attributes, and data modeling attributes. This topic describes these attributes and provides examples.
The System.ComponentModel.DataAnnotations namespace contains the following attributes which are used to enforce validation rules for data applied to the class or member:
|
Validation Attribute |
Description |
|---|---|
|
Uses a custom method for validation. |
|
|
Specifies a particular type of data, such as e-mail address or phone number. |
|
|
Ensures that the value exists in an enumeration. |
|
|
Designates minimum and maximum constraints. |
|
|
Uses a regular expression to determine valid values. |
|
|
Specifies that a value must be provided. |
|
|
Designates maximum and minimum number of characters. |
|
|
Serves as base class for validation attributes. |
All validation attributes derive from the ValidationAttribute class. The logic to determine if a value is valid is implemented in the overridden IsValid method. The Validate method calls the IsValid method and throws a ValidationException if the value is not valid.
To create customized validation checks, you can either create a class that derives from the ValidationAttribute class or create a method that performs the validation check and reference that method when applying the CustomValidationAttribute to the data member. When you create a class that derives from ValidationAttribute, override the IsValid method to provide the logic for your customized validation check.
Currently, the DataGrid control is the only control that automatically applies validation attributes. For an example of using a DataGrid control with a class that contains validation attributes, see the Data Grid Example below. When you do not use the DataGrid control, you must manually validate the values.
Manually Validating Values
When you do not use the DataGrid control to provide the interface for editing data, the validation attributes are not automatically applied. However, you can manually apply the validation test by using the Validator class. You can call the ValidateProperty method on the set accessor of a property to check the value against the validation attributes for the property. You must also set both ValidatesOnExceptions and NotifyOnValidationError properties to true when data binding to receive validation exceptions from validation attributes. For an example of manually applying validation, see the Data Binding Example below.
The System.ComponentModel.DataAnnotations namespace contains the following attributes which are used to specify how data from the class or member is displayed:
|
Display Attribute |
Description |
|---|---|
|
Specifies a particular type of data, such as e-mail address or phone number. |
|
|
Specifies localizable strings for data types and members that are used in the user interface. |
|
|
Designates display and sorting properties when a table is used as a parent table in a foreign key relationship. |
|
|
Specifies how data fields are displayed and formatted. |
|
|
Designates the filtering behavior for a column. |
|
|
Designates the control and values to use to display the associated entity member. |
The display attributes are automatically applied when used with the DataGrid control. You can manually retrieve display attribute values when data binding by using controls such as Label and DescriptionViewer. For an example of using the Label and DescriptionViewer controls with display attributes, see the Data Binding Example below.
The DataTypeAttribute attribute specifies a particular type for a data member and therefore is used as both a validation attribute and display attribute.
The System.ComponentModel.DataAnnotations namespace contains the following attributes which are used to specify the intended use of data members and the relationships between data classes:
|
Data Modeling Attribute |
Description |
|---|---|
|
Specifies that an entity member represents a data relationship, such as a foreign key relationship. |
|
|
Designates that a property participates in optimistic concurrency checks. |
|
|
Specifies whether users should be able to change the value of the entity property. |
|
|
Specifies one or more entity properties to use as the unique identity for the entity. |
|
|
Designates a member as a time stamp value for data versioning. |
This example shows a DataGrid control that enables the user to view and edit data from a data class. Data annotations are applied to the data class to specify display and validation behavior. The validation and display attributes are automatically applied when used with the DataGrid control.
The following example shows the data class named Product with data annotations applied to the members.
The following examples show the page and code-behind file for displaying the data class in a data grid.
<Grid x:Name="LayoutRoot"> <ScrollViewer x:Name="PageScrollViewer"> <StackPanel x:Name="ContentStackPanel"> <TextBlock x:Name="HeaderText" Text="Products"/> <sdk:DataGrid x:Name="DataGrid1" Foreground="Black" AutoGenerateColumns="True"> </sdk:DataGrid> </StackPanel> </ScrollViewer> </Grid>
This example demonstrates a ValidationSummary control that displays errors for three TextBox controls on a form. The validation rules are specified in attributes in the Customer class and manually applied in the set accessor. The ValidatesOnExceptions and NotifyOnValidationError properties are set to true in the data binding.
<!-- NOTE: By convention, the sdk prefix indicates a URI-based XAML namespace declaration for Silverlight SDK client libraries. This namespace declaration is valid for Silverlight 4 only. In Silverlight 3, you must use individual XAML namespace declarations for each CLR assembly and namespace combination outside the scope of the default Silverlight XAML namespace. For more information, see the help topic "Prefixes and Mappings for Silverlight Libraries". --> <UserControl x:Class="ValidationSample.MainPage" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 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" mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"> <Grid x:Name="LayoutRoot" Margin="15" > <Grid.ColumnDefinitions> <ColumnDefinition Width="100"/> <ColumnDefinition Width="300"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="35"/> <RowDefinition Height="35"/> <RowDefinition Height="35"/> <RowDefinition Height="100"/> </Grid.RowDefinitions> <!-- Unbound Date of Birth field --> <sdk:Label Content="Date of Birth" IsRequired="True" Margin="5" /> <StackPanel Orientation="Horizontal" Grid.Column="1"> <sdk:DatePicker Height="23" /> <sdk:DescriptionViewer Description="Please enter your date of birth."/> </StackPanel> <!-- ID Number field --> <sdk:Label Grid.Row="1" Margin="5" Target="{Binding ElementName=tbIdNumber}" /> <StackPanel Orientation="Horizontal" Grid.Column="1" Grid.Row="1"> <TextBox x:Name="tbIdNumber" Height="23" Width="100" Text="{Binding IdNumber, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" /> <sdk:DescriptionViewer Target="{Binding ElementName=tbIdNumber}"/> </StackPanel> <!-- Name field --> <sdk:Label Grid.Row="2" Margin="5" Target="{Binding ElementName=spName}" PropertyPath="FirstName" /> <StackPanel Orientation="Horizontal" Grid.Column="1" Grid.Row="2"> <StackPanel x:Name="spName" Orientation="Horizontal" > <TextBox x:Name="tbFirstName" Text="{Binding FirstName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" Height="23" Width="100" /> <TextBox x:Name="tbLastName" Text="{Binding LastName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" Height="23" Width="100" /> </StackPanel> <sdk:DescriptionViewer Target="{Binding ElementName=spName}" PropertyPath="FirstName"/> </StackPanel> <!-- ValidationSummary --> <sdk:ValidationSummary Grid.ColumnSpan="2" Grid.Row="3" /> </Grid> </UserControl>