@@ -326,11 +326,31 @@ protected bool TrySetProperty<TModel, T>(T oldValue, T newValue, IEqualityCompar
326326 SetProperty ( oldValue , newValue , comparer , model , callback , propertyName ) ;
327327 }
328328
329+ /// <summary>
330+ /// Clears the validation errors for a specified property or for the entire entity.
331+ /// </summary>
332+ /// <param name="propertyName">
333+ /// The name of the property to clear validation errors for.
334+ /// If a <see langword="null"/> or empty name is used, all entity-level errors will be cleared.
335+ /// </param>
336+ protected void ClearErrors ( string ? propertyName = null )
337+ {
338+ // Clear entity-level errors when the target property is null or empty
339+ if ( string . IsNullOrEmpty ( propertyName ) )
340+ {
341+ ClearAllErrors ( ) ;
342+ }
343+ else
344+ {
345+ ClearErrorsForProperty ( propertyName ! ) ;
346+ }
347+ }
348+
329349 /// <inheritdoc cref="INotifyDataErrorInfo.GetErrors(string)"/>
330350 [ Pure ]
331- public IEnumerable < ValidationResult > GetErrors ( string ? propertyName )
351+ public IEnumerable < ValidationResult > GetErrors ( string ? propertyName = null )
332352 {
333- // Entity -level errors when the target property is null or empty
353+ // Get entity -level errors when the target property is null or empty
334354 if ( string . IsNullOrEmpty ( propertyName ) )
335355 {
336356 // Local function to gather all the entity-level errors
@@ -495,6 +515,59 @@ private bool TryValidateProperty(object? value, string? propertyName, out IReadO
495515 return isValid ;
496516 }
497517
518+ /// <summary>
519+ /// Clears all the current errors for the entire entity.
520+ /// </summary>
521+ private void ClearAllErrors ( )
522+ {
523+ if ( this . totalErrors == 0 )
524+ {
525+ return ;
526+ }
527+
528+ // Clear the errors for all properties with at least one error, and raise the
529+ // ErrorsChanged event for those properties. Other properties will be ignored.
530+ foreach ( var propertyInfo in this . errors )
531+ {
532+ bool hasErrors = propertyInfo . Value . Count > 0 ;
533+
534+ propertyInfo . Value . Clear ( ) ;
535+
536+ if ( hasErrors )
537+ {
538+ ErrorsChanged ? . Invoke ( this , new DataErrorsChangedEventArgs ( propertyInfo . Key ) ) ;
539+ }
540+ }
541+
542+ this . totalErrors = 0 ;
543+
544+ OnPropertyChanged ( HasErrorsChangedEventArgs ) ;
545+ }
546+
547+ /// <summary>
548+ /// Clears all the current errors for a target property.
549+ /// </summary>
550+ /// <param name="propertyName">The name of the property to clear errors for.</param>
551+ private void ClearErrorsForProperty ( string propertyName )
552+ {
553+ if ( ! this . errors . TryGetValue ( propertyName ! , out List < ValidationResult > ? propertyErrors ) ||
554+ propertyErrors . Count == 0 )
555+ {
556+ return ;
557+ }
558+
559+ propertyErrors . Clear ( ) ;
560+
561+ this . totalErrors -- ;
562+
563+ if ( this . totalErrors == 0 )
564+ {
565+ OnPropertyChanged ( HasErrorsChangedEventArgs ) ;
566+ }
567+
568+ ErrorsChanged ? . Invoke ( this , new DataErrorsChangedEventArgs ( propertyName ) ) ;
569+ }
570+
498571#pragma warning disable SA1204
499572 /// <summary>
500573 /// Throws an <see cref="ArgumentNullException"/> when a property name given as input is <see langword="null"/>.
0 commit comments