1

I have a working WPF dialog that uses DataGrid. The DataGrid is set to have ItemsSource={Binding SomeCollection, Mode=TwoWay}. This setup works fine, I can read values and update them from UI.

Later I have added Converters to validate values. I show blank when validation fails. Now I am interested in getting the original values back in case if validation fails.

What options do i have here?

vrrathod
  • 1,230
  • 2
  • 18
  • 28

1 Answers1

6

I have never used a converter for validation. Instead I use items that implement IDataErrorInfo with an attribute in the databinding attribute for ValidatesOnDataErrors=True.

Using this method of validation, the original value is retained, and the object returns the errors value (in my case a string saying what the error is). My View's controls have a custom validation item which adds a red border which fades over time, and a tooltip that pops up on mouse hover.

Then you just need to put your validation rules in the data classes you are displaying:

Private Sub OnAddress1Changed()
    Me.RemoveError("Address1")
    If _Address1 Is Nothing OrElse _Address1.Trim = "" Then
        Me.AddError("Address1", "Please enter a valid Address Line")
    End If
    OnPropertyChanged("CanShip")
End Sub


Private m_validationErrors As New Dictionary(Of String, String)
Private Sub AddError(ByVal ColName As String, ByVal Msg As String)
    If Not m_validationErrors.ContainsKey(ColName) Then
        m_validationErrors.Add(ColName, Msg)
    End If
End Sub
Private Sub RemoveError(ByVal ColName As String)
    If m_validationErrors.ContainsKey(ColName) Then
        m_validationErrors.Remove(ColName)
    End If
End Sub


Public ReadOnly Property [Error]() As String Implements System.ComponentModel.IDataErrorInfo.Error
    Get
        If m_validationErrors.Count > 0 Then
            Return "Shipment 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

Edit

And just for the heck of it, I will put an example validation template in to show others how to hook it up.

<Style x:Key="ToolTipValidation" TargetType="{x:Type Control}">
                                <Setter Property="Validation.ErrorTemplate">
                                        <Setter.Value>
                                                <ControlTemplate>
                                                        <Border BorderBrush="Red" BorderThickness="2,1,2,1">
                                                                <AdornedElementPlaceholder/>
                                                        </Border>
                                                </ControlTemplate>
                                        </Setter.Value>
                                </Setter>
                                <Style.Triggers>
                                        <Trigger Property="Validation.HasError" Value="True">
                                                <Setter Property="ToolTip" Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}"/>
                                        </Trigger>
                                </Style.Triggers>
                        </Style>

Finally: A MSDN article on implementing Validation

A video to go with it. Video number 4

CodeWarrior
  • 7,388
  • 7
  • 51
  • 78
  • +1 for an awesome way to do it. I have updated my app to be MVVM, and added validation logic in VM before committing it to the actual data. – vrrathod Jun 21 '11 at 19:56
  • You might also check out windowsclient.net (another microsoft site dedicated to WinForms and WPF development). Thanks for the upvote and answer! – CodeWarrior Jun 21 '11 at 20:14