Edit this page

Using DataAnnotation Attributes

Validating Input Through Data Annotations

With the Silverlight 4.0 platform you can take advantage of the System.ComponentModel.DataAnnotations assembly. The following code snippet demonstrates how to use data annotation attributes to validate a property value. It is even better when you use RIA services, since this code will be automatically added for you by the RIA Service's code generator.

Example 1: Creating DataAnnotationAttributesValidationViewModel class

public class DataAnnotationAttributesValidationViewModel : ViewModelBase
{
    private double doubleValue;
    private string stringValue;
    private decimal decimalValue;
    private DateTime dateTimeValue;
    [Range(-100d, 100d)]
    public double DoubleValue
    {
        get { return doubleValue; }
        set
        {
            Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "DoubleValue" });
            doubleValue = value;
            this.OnPropertyChanged("DoubleValue");
        }
    }
    [Range(typeof(decimal), "-100", "100")]
    public decimal DecimalValue
    {
        get { return decimalValue; }
        set
        {
            Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "DecimalValue" });
            decimalValue = value;
            this.OnPropertyChanged("DecimalValue");
        }
    }
    [Range(typeof(DateTime), "01.01.1900", "01.01.2099")]
    public DateTime DateTimeValue
    {
        get { return dateTimeValue; }
        set
        {
            Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "DateTimeValue" });
            dateTimeValue = value;
            this.OnPropertyChanged("DateTimeValue");
        }
    }
    [StringLength(6)]
    [Required()]
    public string StringValue
    {
        get { return stringValue; }
        set
        {
            Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "StringValue" });
            stringValue = value;
            this.OnPropertyChanged("StringValue");
        }
    }
}
Public Class DataAnnotationAttributesValidationViewModel
    Inherits ViewModelBase
    Private m_doubleValue As Double
    Private m_stringValue As String
    Private m_decimalValue As Decimal
    Private m_dateTimeValue As Date
    <Range(-100.0, 100.0)>
    Public Property DoubleValue() As Double
        Get
            Return m_doubleValue
        End Get
        Set(value As Double)
            Validator.ValidateProperty(Value, New ValidationContext(Me, Nothing, Nothing) With {.MemberName = "DateTimeValue"})
            m_doubleValue = Value
            Me.OnPropertyChanged("DoubleValue")
        End Set
    End Property
    <Range(GetType(Decimal), "-100", "100")>
    Public Property DecimalValue() As Decimal
        Get
            Return m_decimalValue
        End Get
        Set(value As Decimal)
            Validator.ValidateProperty(Value, New ValidationContext(Me, Nothing, Nothing) With {.MemberName = "DecimalValue"})
            m_decimalValue = Value
            Me.OnPropertyChanged("DecimalValue")
        End Set
    End Property
    <Range(GetType(Date), "01.01.1900", "01.01.2099")>
    Public Property DateTimeValue() As Date
        Get
            Return m_dateTimeValue
        End Get
        Set(value As Date)
            Validator.ValidateProperty(Value, New ValidationContext(Me, Nothing, Nothing) With {.MemberName = "DateTimeValue"})
            m_dateTimeValue = Value
            Me.OnPropertyChanged("DateTimeValue")
        End Set
    End Property
    <StringLength(6)>
    <Required>
    Public Property StringValue() As String
        Get
            Return m_stringValue
        End Get
        Set(value As String)
            Validator.ValidateProperty(Value, New ValidationContext(Me, Nothing, Nothing) With {.MemberName = "StringValue"})
            m_stringValue = Value
            Me.OnPropertyChanged("StringValue")
        End Set
    End Property
End Class

In order to use DataAnnotations you should add a reference to the System.ComponentModel.DataAnnotations assembly.

Note that you have to invoke the Validator.ValidateProperty method before setting a new value in the property setter.

Now we need to define several RadMaskedInput controls in XAML for displaying the sample data:

Example 2: Defining several RadMaskedInput controls

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <telerik:RadMaskedNumericInput Grid.Row="0" Width="200" AllowInvalidValues="True"
            Margin="10, 10, 10, 0" ErrorMessage="{Binding Path=Text, ElementName=customErrorMessage}"
            InputBehavior="Insert"
            Value="{Binding Path=DoubleValue, Mode=TwoWay, ValidatesOnExceptions=True}" />
    <telerik:RadMaskedCurrencyInput  Grid.Row="1" Width="200" AllowInvalidValues="True"
            Margin="10, 10, 10, 0" ErrorMessage="{Binding Path=Text, ElementName=customErrorMessage}"
            InputBehavior="Insert"
            Value="{Binding Path=DecimalValue, Mode=TwoWay, ValidatesOnExceptions=True}" />
    <telerik:RadMaskedDateTimeInput  Grid.Row="2" Width="200" AllowInvalidValues="True"
            Margin="10, 10, 10, 0" ErrorMessage="{Binding Path=Text, ElementName=customErrorMessage}"
            Value="{Binding Path=DateTimeValue, Mode=TwoWay, ValidatesOnExceptions=True}" />
    <telerik:RadMaskedTextInput  Grid.Row="3" Width="200" Margin="10"
            ErrorMessage="{Binding Path=Text, ElementName=customErrorMessage}" AllowInvalidValues="True"
            Value="{Binding Path=StringValue, Mode=TwoWay,ValidatesOnExceptions=True}" />
</Grid>

Note that you have set AllowInvalidValues to True. This ensures that the Setter of the properties will be fired even if the DataAnnotaion Validation does not succeed.

And finally we need to set the DataContext accordingly:

Example 3: Setting the DataContext to the view model

this.DataContext = new DataAnnotationAttributesValidationViewModel();
Me.DataContext = New DataAnnotationAttributesValidationViewModel()

Below you can see how the MaskedInputs are being validated:

Rad Masked Input-Validation-Data AnnotationsSL

You can see a live demo demonstrating the DataValidation feature here.

The RadMaskedInput controls support two properties that allow you to further customize your DataValidation scenarios:

  • IsMaskValid - when this property is False, the entered input is invalid

  • IsValidationHintVisisble - this property allows you to turn on and off the MaskedInput controls validation hint

The data annotation attributes fall into three categories: validation attributes, display attributes, and data modeling attributes. You can find more info here.

You can find example with RegularExpression attribute in the following section.

Regular Expressions

The MaskedInput suite of controls allow validation through Regular Expressions. In order to implement regex validation you will need a view model implementing the INotifyPropertyChanged interface. For the purpose of this tutorial we will define a ViewModel that contains Email and WebAddress properties. For each property we will apply a regular expression to validate the user's input in the MaskedInput control that will display the property accordingly.

First, we need a view model:

Example 4: Creating MaskedInputViewModel class

public class MaskedInputViewModel : ViewModelBase
{
    private string email = "username@email.com";
    /// <summary>
    ///     Gets or sets the email.
    /// </summary>
    [RegularExpression(@"\b[a-z0-9.%-]+@[a-z0-9.-]+.[a-z]{2,4}\b", ErrorMessage = "Invalid Email Address.")]
    public string Email
    {
        get
        {
            return this.email;
        }
        set
        {
            if (this.email != value)
            {
                Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Email" });
                this.email = value;
                OnPropertyChanged("Email");
            }
        }
    }
    private string webAddress = "http://www.sampleaddress.com";&#13;    /// <summary>
    ///     Gets or sets the webAddress.
    /// </summary>
    [RegularExpression(@"http://www.+\b[a-z0-9.%-]+.[a-z]{2,4}\b", ErrorMessage = "Invalid Web Address.")]
    public string WebAddress
    {
        get
        {
            return this.webAddress;
        }
        set
        {
            if (this.webAddress != value)
            {
                Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "WebAddress" });
                this.webAddress = value;
                OnPropertyChanged("WebAddress");
            }
        }
    }
}
Public Class MaskedInputViewModel
    Inherits ViewModelBase
    Private m_email As String = "username@email.com"
    ''' <summary>
    '''     Gets or sets the email.
    ''' </summary>
    <RegularExpression("\b[a-z0-9.%-]+@[a-z0-9.-]+.[a-z]{2,4}\b", ErrorMessage:="Invalid Email Address.")>
    Public Property Email() As String
        Get
            Return Me.m_email
        End Get
        Set
            If Me.m_email <> Value Then
                Validator.ValidateProperty(Value, New ValidationContext(Me, Nothing, Nothing) With {.MemberName = "Email"})
                Me.m_email = Value
                OnPropertyChanged("Email")
            End If
        End Set
    End Property
    Private m_webAddress As String = "http://www.sampleaddress.com"&#13;    ''' <summary>
    '''     Gets or sets the webAddress.
    ''' </summary>
    <RegularExpression("http://www.+\b[a-z0-9.%-]+.[a-z]{2,4}\b", ErrorMessage:="Invalid Web Address.")>
    Public Property WebAddress() As String
        Get
            Return Me.m_webAddress
        End Get
        Set
            If Me.m_webAddress <> Value Then
                Validator.ValidateProperty(Value, New ValidationContext(Me, Nothing, Nothing) With {.MemberName = "WebAddress"})
                Me.m_webAddress = Value
                OnPropertyChanged("WebAddress")
            End If
        End Set
    End Property
End Class

Note that you have to invoke the Validator.ValidateProperty method before setting a new value in the property setter.

In the above MaskedInputViewModel implementation it is important to note the regular expressions that validate the Email and WebAddress properties, as well as the custom ErrorMessage that is defined for each property. In order to apply such attributes that specify validation rules, you need to add a reference to the System.ComponentModel.DataAnnotations namespace.

Then you can define the RadMaskedInput controls that will display the Email and WebAddress business properties:

Example 5: Defining RadMaskedInput controls in XAML

<telerik:RadMaskedTextInput AllowInvalidValues="True" Value="{Binding Path=Email, Mode=TwoWay, ValidatesOnExceptions=True}" VerticalAlignment="Center"/>
<telerik:RadMaskedTextInput AllowInvalidValues="True" Value="{Binding Path=WebAddress, Mode=TwoWay, ValidatesOnExceptions=True}" Mask="a30"
                VerticalAlignment="Center" />

Note that you have set AllowInvalidValues to True. This ensures that the Setter of the properties will be fired even if the DataAnnotaion Validation does not succeed.

And finally you need to set the MaskedInputViewModel as DataContext of the MaskedTextInput controls:

Example 6: Setting the DataContext in XAML

<UserControl  
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&#13;     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&#13;     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"&#13;     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"&#13;     xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"&#13;     xmlns:vm="clr-namespace:MaskedInputValidation"
     d:DesignHeight="300"
     d:DesignWidth="400"
     mc:Ignorable="d">
    <UserControl.DataContext>
        <vm:MaskedInputViewModel />
    </UserControl.DataContext>
    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel>
            <StackPanel Margin="5" Orientation="Horizontal">
                <TextBlock VerticalAlignment="Center" Text="Enter Email Address: " />
                <telerik:RadMaskedTextInput VerticalAlignment="Center" AllowInvalidValues="True" Value="{Binding Path=Email, Mode=TwoWay, ValidatesOnExceptions=True}" />
            </StackPanel>
            <StackPanel Margin="5" Orientation="Horizontal">
                <TextBlock VerticalAlignment="Center" Text="Enter Web Address: " />
                <telerik:RadMaskedTextInput VerticalAlignment="Center" AllowInvalidValues="True"
                                    Mask="a30"
                                    Value="{Binding Path=WebAddress, Mode=TwoWay, ValidatesOnExceptions=True}" />
            </StackPanel>
        </StackPanel>
    </Grid>
</UserControl>