22// The .NET Foundation licenses this file to you under the MIT license.
33// See the LICENSE file in the project root for more information.
44
5+ using System . Collections ;
56using System . ComponentModel . DataAnnotations ;
67
78using INotifyDataErrorInfo = System . ComponentModel . INotifyDataErrorInfo ;
@@ -29,7 +30,7 @@ public string PropertyName
2930 /// Identifies the <see cref="PropertyName"/> dependency property.
3031 /// </summary>
3132 public static readonly DependencyProperty PropertyNameProperty =
32- DependencyProperty . Register ( nameof ( PropertyName ) , typeof ( string ) , typeof ( InputValidationAdorner ) , new PropertyMetadata ( null ) ) ;
33+ DependencyProperty . Register ( nameof ( PropertyName ) , typeof ( string ) , typeof ( InputValidationAdorner ) , new PropertyMetadata ( null , ( s , e ) => ( s as InputValidationAdorner ) ? . RefreshErrors ( ) ) ) ;
3334
3435 /// <summary>
3536 /// Gets or sets the <see cref="INotifyDataErrorInfo"/> context object to use for validation.
@@ -44,7 +45,7 @@ public INotifyDataErrorInfo NotifyDataErrorInfo
4445 /// Identifies the <see cref="NotifyDataErrorInfo"/> dependency property.
4546 /// </summary>
4647 public static readonly DependencyProperty NotifyDataErrorInfoProperty =
47- DependencyProperty . Register ( nameof ( NotifyDataErrorInfo ) , typeof ( INotifyDataErrorInfo ) , typeof ( InputValidationAdorner ) , new PropertyMetadata ( null ) ) ;
48+ DependencyProperty . Register ( nameof ( NotifyDataErrorInfo ) , typeof ( INotifyDataErrorInfo ) , typeof ( InputValidationAdorner ) , new PropertyMetadata ( null , ( s , e ) => ( s as InputValidationAdorner ) ? . RefreshErrors ( ) ) ) ;
4849
4950 /// <summary>
5051 /// Gets or sets whether the validation adorners is displayed (handled automatically).
@@ -76,6 +77,8 @@ public string ValidationMessage
7677 public static readonly DependencyProperty ValidationMessageProperty =
7778 DependencyProperty . Register ( nameof ( ValidationMessage ) , typeof ( string ) , typeof ( InputValidationAdorner ) , new PropertyMetadata ( null ) ) ;
7879
80+ // TODO: Do we consider an InfoBar style Severity property?
81+
7982 /// <summary>
8083 /// Initializes a new instance of the <see cref="InputValidationAdorner"/> class.
8184 /// </summary>
@@ -103,45 +106,47 @@ protected override void OnAttached()
103106
104107 private void INotifyDataErrorInfo_ErrorsChanged ( object ? sender , DataErrorsChangedEventArgs e )
105108 {
106- if ( NotifyDataErrorInfo is not null )
107- {
108- // Reset state
109- if ( ! NotifyDataErrorInfo . HasErrors )
110- {
111- HasValidationFailed = false ;
112- ValidationMessage = string . Empty ;
113- return ;
114- }
109+ RefreshErrors ( ) ;
110+ }
115111
116- if ( e . PropertyName == PropertyName )
112+ private void RefreshErrors ( )
113+ {
114+ // Check if we have any errors for our specified property
115+ if ( NotifyDataErrorInfo is not null
116+ && PropertyName is not null
117+ && NotifyDataErrorInfo . GetErrors ( PropertyName ) is IEnumerable errors
118+ && errors . Cast < object > ( ) . Any ( ) )
119+ {
120+ // Build up error messages depending on error collection type.
121+ StringBuilder message = new ( ) ;
122+ if ( errors is IEnumerable < ValidationResult > validationResults )
117123 {
118- HasValidationFailed = true ;
119-
120- var errors = NotifyDataErrorInfo . GetErrors ( e . PropertyName ) ;
121-
122- StringBuilder message = new ( ) ;
123- if ( errors is IEnumerable < ValidationResult > validationResults )
124+ foreach ( ValidationResult result in validationResults )
124125 {
125- foreach ( ValidationResult result in validationResults )
126- {
127- message . AppendLine ( result . ErrorMessage ) ;
128- }
126+ message . AppendLine ( result . ErrorMessage ) ;
129127 }
130- else if ( errors is IEnumerable < string > stringErrors )
128+ }
129+ else if ( errors is IEnumerable < string > stringErrors )
130+ {
131+ foreach ( string result in stringErrors )
131132 {
132- foreach ( string result in stringErrors )
133- {
134- message . AppendLine ( result ) ;
135- }
133+ message . AppendLine ( result ) ;
136134 }
137- else
138- {
139- // TODO: Not sure if should handle more types of collections here?
140- throw new ArgumentException ( "The errors returned by INotifyDataErrorInfo.GetErrors must be of type IEnumerable<ValidationResult> or IEnumerable<string>." ) ;
141- }
142-
143- ValidationMessage = message . ToString ( ) . Trim ( ) ;
144135 }
136+ else
137+ {
138+ // TODO: Not sure if should handle more types of collections here?
139+ throw new ArgumentException ( "The errors returned by INotifyDataErrorInfo.GetErrors must be of type IEnumerable<ValidationResult> or IEnumerable<string>." ) ;
140+ }
141+
142+ HasValidationFailed = true ;
143+ ValidationMessage = message . ToString ( ) . Trim ( ) ;
144+ }
145+ else
146+ {
147+ // Hide if we have no object or errors to validate against.
148+ HasValidationFailed = false ;
149+ ValidationMessage = string . Empty ;
145150 }
146151 }
147152
0 commit comments