In Silverlight, there are multiple methods for verifying the validity of data entity classes, such as using TargetNullValue, FailBackValue, ValidatesOnExceptions ....., using these methods can solve common problems, but it is obviously not the most effective tool for complex data verification. For example, the INotifyDataErrorInfo interface can be flexibly used to verify the validity of a single attribute.
MSDN INotifyDataErrorInfor is defined as follows:
// Summary:
// Defines members that data entity classes can implement to provide custom,
// asynchronous validation support.
public interface INotifyDataErrorInfo
{
// Summary:
// Gets a value that indicates whether the object has validation errors.
//
// Returns:
// true if the object currently has validation errors; otherwise, false.
bool HasErrors { get; }
// Summary:
// Occurs when the validation errors have changed for a property or for the
// entire object.
event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
// Summary:
// Gets the validation errors for a specified property or for the entire object.
//
// Parameters:
// propertyName:
// The name of the property to retrieve validation errors for, or null or System.String.Empty
// to retrieve errors for the entire object.
//
// Returns:
// The validation errors for the property or object.
IEnumerable GetErrors(string propertyName);
}
From the definition of INotifyDataErrorInfo, you can understand its role. The data entity class can inherit INotifyDataErrorInfo to verify the validity of the class to meet business requirements. The following uses the INotifyDataErrorInfo interface implemented by the Student object class as an example.
Student definition:
Public class Student: INotifyPropertyChanged, INotifyDataErrorInfo
{
// Stores error messages. A Property may correspond to multiple error messages.
Private Dictionary <string, List <string> errors = new Dictionary <string, List <string> ();
// Implement INotifyPropertyChanged
Public event PropertyChangedEventHandler PropertyChanged;
Public void OnPropertyChanged (PropertyChangedEventArgs e)
{
If (PropertyChanged! = Null)
{
PropertyChanged (this, e );
}
}
// Implement INotifyDataErrorInfo
Public event EventHandler <DataErrorsChangedEventArgs> ErrorsChanged;
Public IEnumerable GetErrors (string propertyName)
{
If (string. IsNullOrEmpty (propertyName ))
{
Return null;
}
Else
{
If (errors. ContainsKey (propertyName ))
{
Return errors [propertyName];
}
}
Return null;
}
Public bool HasErrors
{
Get
{
Return (errors. Count> 0 );
}
}
private void SetErrors(string propertyName, List<string> propertyErrors)
{
errors.Remove(propertyName);
errors.Add(propertyName, propertyErrors);
if (ErrorsChanged != null)
{
ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
}
private void ClearErrors(string propertyName)
{
errors.Remove(propertyName);
if (ErrorsChanged != null)
{
ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
}
private string name;
private int age;
public String Name
{
get
{
return name;
}
set
{
name = value;
List<string> errors = new List<string>();
bool valid = true;
// Data verification
If (name. Trim (). Contains (""))
{
Errors. Add ("the name cannot contain spaces ");
Valid = false;
}
If (name. Length <2 | name. Length> 4)
{
Errors. Add ("the name length cannot be less than 2 or higher than 4 ");
Valid = false;
}
If (! Valid)
{
SetErrors ("Name", errors );
}
Else
{
ClearErrors ("Name ");
}
}
}
Public int Age
{
Get
{
Return age;
}
Set
{
Age = value;
If (age <0 | age> 150)
{
List <string> errors = new List <string> ();
Errors. Add ("Age cannot be less than 0 or greater than 150 ");
SetErrors ("Age", errors );
}
Else
{
ClearErrors ("Age ");
}
}
}
}
In MainPage XAML code, validatesonpolicydataerrors = True must be set when binding data.
<Grid x: Name = "LayoutRoot" Background = "White" BindingValidationError = "LayoutRoot_BindingValidationError">
<Grid. RowDefinitions>
<RowDefinition Height = "40"> </RowDefinition>
<RowDefinition Height = "40"> </RowDefinition>
<RowDefinition Height = "40"> </RowDefinition>
<RowDefinition Height = "Auto"> </RowDefinition>
</Grid. RowDefinitions>
<Grid. ColumnDefinitions>
<ColumnDefinition> </ColumnDefinition>
<ColumnDefinition> </ColumnDefinition>
</Grid. ColumnDefinitions>
<TextBlock Text = "name:" HorizontalAlignment = "Right" verticalignment = "Center"> </TextBlock>
<TextBox x: Name = "txtName" Text = "{Binding Name, Mode = TwoWay, ValidatesOnExceptions = True,
Validatesonpolicydataerrors = True, NotifyOnValidationError = True} "Width =" 150 "Grid. Column =" 1 "HorizontalAlignment =" Left "verticalignment =" Center ">
</TextBox>
<TextBlock Text = "Age:" HorizontalAlignment = "Right" Grid. Row = "1" verticalignment = "Center"> </TextBlock>
<TextBox x: Name = "txtAge" Text = "{Binding Age, Mode = TwoWay, ValidatesOnExceptions = True,
Validatesonpolicydataerrors = True, NotifyOnValidationError = True} "Width =" 150 "Grid. Column =" 1 "Grid. Row =" 1 "HorizontalAlignment =" Left "verticalignment =" Center ">
</TextBox>
<Button x: Name = "Submit" Content = "Submit The Data" HorizontalAlignment = "Left" Grid. row = "2" Grid. column = "1" Click = "Submit_Click" VerticalAlignment = "Center"> </Button>
<TextBlock x: Name = "Summary" Text = "no error message" VerticalAlignment = "Center" Grid. column = "1" Grid. row = "3"> </TextBlock>
</Grid>
MainPage background code:
Public MainPage ()
{
InitializeComponent ();
Student product = new Student ();
LayoutRoot. DataContext = product;
}
Private void LayoutRoot_BindingValidationError (object sender, ValidationErrorEventArgs e)
{
// No Exception may exist, but an error message exists.
If (e. Error. Exception! = Null)
{
// Exception Handling Code
}
Else
{
Summary. Text = e. Error. ErrorContent. ToString ();
TxtName. Focus ();
}
}
Running result:
If you want to implement complex data verification, INotifyDataErrorInfo is also a good choice. If you have any shortcomings, please point out.