Click here to Skip to main content
15,867,594 members
Articles / Desktop Programming / WPF
Tip/Trick

Data validation in WPF

Rate me:
Please Sign up or sign in to vote.
4.71/5 (4 votes)
5 Feb 2014CPOL 16.4K   5   1
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:

VB.NET
#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

VB.NET
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

XML
<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:

XML
<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

Image 1

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Belgium Belgium
I've been a developer since the late 90's, going from Mainframe to Object Oriented. I'm in a small team, developing inhouse WPF applications, used for commercial support.

I'll try to share information and tips and tricks for developing in WPF, explain how we solved issues, what we did to meet our goal.

If you have any questions, remarks, suggestions... please let me know !

regs,
Wim

Comments and Discussions

 
QuestionEvents in your Data Validation Pin
JohnEdwards196827-Apr-14 16:36
JohnEdwards196827-Apr-14 16:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.