65.9K
CodeProject is changing. Read more.
Home

Data validation in WPF

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.71/5 (4 votes)

Feb 5, 2014

CPOL
viewsIcon

16688

how to implement data validation via regular expressions in a WPF application

Starting with the model

After adding a table (conversation topics) in the model in the data layer, I created a partial public class of that table. This class has to implement iDataErrorInfo and you can add the following code:

#Region "IDataErrorInfo Members"
    Private m_validationErrors As New Dictionary(Of String, String)
 
    Private Sub AddError(ByVal columnName As String, ByVal msg As String)
        If Not m_validationErrors.ContainsKey(columnName) Then
            m_validationErrors.Add(columnName, msg)
        End If
    End Sub
 
    Private Sub RemoveError(ByVal columnName As String)
        If m_validationErrors.ContainsKey(columnName) Then
            m_validationErrors.Remove(columnName)
        End If
    End Sub
 
    Public ReadOnly Property HasErrors() As Boolean
        Get
            Return m_validationErrors.Count > 0
        End Get
    End Property
 
    Public ReadOnly Property [Error] As String Implements System.ComponentModel.IDataErrorInfo.Error
        Get
            If m_validationErrors.Count > 0 Then
                Return "Customer data is invalid"
            Else
                Return Nothing
            End If
        End Get
    End Property
 
    Default Public ReadOnly Property Item(ByVal columnName As String) As String Implements System.ComponentModel.IDataErrorInfo.Item
        Get
            If m_validationErrors.ContainsKey(columnName) Then
                Return m_validationErrors(columnName).ToString
            Else
                Return Nothing
            End If
        End Get
    End Property
 
#End Region

Add the onchanged event of the field that should be validated

Private Sub OnlConTopFChanged()
        _regex = New Regex("([A-Za-z0-9-]+)", RegexOptions.IgnoreCase)
        If _lConTopF Is Nothing OrElse Not _regex.Match(_lConTopF.ToString()).Success Then
            Me.AddError("lConTopF", "Fill in a value.")
        Else
            Me.RemoveError("lConTopF")
        End If
    End Sub
 
    Private Sub OnlConTopNChanged()
        _regex = New Regex("([A-Za-z0-9-]+)", RegexOptions.IgnoreCase)
        If _lConTopN Is Nothing OrElse Not _regex.Match(_lConTopN.ToString()).Success Then
            Me.AddError("lConTopN", "Fill in a value.")
        Else
            Me.RemoveError("lConTopN")
        End If
    End Sub

Continue with the User interface

Make sure to bind you control to the correct field (in our case lConTopF and lConTopN) Add ValidatesOnDataErrors = true to make it validate Add UpdateSourceTrigger=propertychanged to make sure it validates everytime the value changes

       <TextBox Name="txtNameNL"
                     Grid.Row="1"
                     Grid.Column="1"
                     Margin="5"
                     Text="{Binding Path=ObsConTop.ConTop.lConTopN,
                                    ValidatesOnDataErrors=True,
                                    UpdateSourceTrigger=PropertyChanged}" />
            <TextBox Name="txtNameFR"
                     Grid.Row="2"
                     Grid.Column="1"
                     Margin="5"
                     Text="{Binding Path=ObsConTop.ConTop.lConTopF,
                                    ValidatesOnDataErrors=True,
                                    UpdateSourceTrigger=PropertyChanged}" />

Set a general style for indicating an error

You can do this in Application.Xaml:

	<Style x:Key="myErrorTemplate" TargetType="Control">
                <Setter Property="Validation.ErrorTemplate">
                    <Setter.Value>
                        <ControlTemplate>
                            <DockPanel LastChildFill="True">
                                <Ellipse Width="15"
                                         Height="15"
                                         Margin="-25,0,0,0"
                                         DockPanel.Dock="Right"
                                         Fill="Red"
                                         StrokeThickness="1"
                                         ToolTip="{Binding ElementName=myTextbox,
                                                           Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                                    <Ellipse.Stroke>
                                        <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
                                            <GradientStop Offset="0" Color="#FFFA0404" />
                                            <GradientStop Offset="1" Color="#FFC9C7C7" />
                                        </LinearGradientBrush>
                                    </Ellipse.Stroke>
                                </Ellipse>
                                <TextBlock Margin="-15,5,0,0"
                                           DockPanel.Dock="Right"
                                           FontSize="9pt"
                                           FontWeight="Bold"
                                           Foreground="White"
                                           ToolTip="{Binding ElementName=myControl,
                                                             Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                                    !
                                </TextBlock>
                                <Border BorderBrush="Red" BorderThickness="1">
                                    <AdornedElementPlaceholder Name="myControl" />
                                </Border>
                            </DockPanel>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <Trigger Property="Validation.HasError" Value="true">
                        <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}" />
                    </Trigger>
                </Style.Triggers>
            </Style>
            <Style BasedOn="{StaticResource myErrorTemplate}" TargetType="TextBox" />
            <Style BasedOn="{StaticResource myErrorTemplate}" TargetType="CheckBox" />
            <Style BasedOn="{StaticResource myErrorTemplate}" TargetType="ComboBox" />

Result