I am developing a WPF application (using MVVM) and have implemented IDataErrorInfo on my ViewModel. Part of my validation checks that mandatory fields have been entered. This works perfectly for editing existing records but doesn't provide a nice user experience when adding new records. As soon as I load the new view, the mandatory fields are highlighted as invalid.
Is there a (preferably non-hacky) solution to this? It seems a pretty standard thing to want, so I'm hoping I'm missing something simple.
Use a flag that indicates whether the record is new. Check this flag in your implementation of IDataErrorInfo
, and set the flag to true the first time the user tries to validate the input.
Instead of using "ValidatesOnDataErrors=True" you can add DataErrorValidationRule manually, with ValidatesOnTargetUpdated attribute:
<TextBox>
<TextBox.Text>
<Binding Path="..." ValidatesOnExceptions="true">
<Binding.ValidationRules>
<DataErrorValidationRule ValidatesOnTargetUpdated="false"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
I generally have a sub on my entity or dataclass that removes all entries from my Error dictionary after initialization. I call it after instancing.
You could go a step further and have an initialized field (boolean) that gets set to False for New objects, True for existing objects.
You don't want the user presented with a bunch of error/validation templates just because they have generated a new object and haven't populated it with data yet.
ViewModel Example
In this example I have the Property from my ViewModel. When the Shipment Object gets loaded, the property calls the Clear method on the error dictionary. If the Shipment is a persisted record from the database, it should have valid data as it had to be validated in order to be saved to the DB. if it is new, the entries get deleted and the user is presented with a fresh form ready for input.
Public Property ShipmentRecord() As Shipment
Get
Return _shpShipmentRecord
End Get
Set(ByVal value As Shipment)
_shpShipmentRecord = value
ShipmentRecord.m_dirtyFields.Clear()
OnPropertyChanged("ShipmentRecord")
End Set
End Property
Unfortunately this was the first example I could find, and it accesses the m_dirtyFields dictionary directly (it was originally private, but I set it as Friend.) Under most circumstances I would create a method to access the dictionary instead.
来源:https://stackoverflow.com/questions/7231239/how-can-i-stop-idataerrorinfo-from-firing-for-new-items