7
7
using System . ComponentModel ;
8
8
using System . ComponentModel . DataAnnotations ;
9
9
using System . Linq ;
10
+ using System . Reflection ;
10
11
using System . Text . RegularExpressions ;
11
12
using Microsoft . Toolkit . Mvvm . ComponentModel ;
12
13
using Microsoft . VisualStudio . TestTools . UnitTesting ;
@@ -335,6 +336,54 @@ public void Test_ObservableValidator_ValidateAllProperties()
335
336
model . Age = - 10 ;
336
337
337
338
model . ValidateAllProperties ( ) ;
339
+
340
+ Assert . IsTrue ( model . HasErrors ) ;
341
+ Assert . IsTrue ( events . Count == 1 ) ;
342
+ Assert . IsTrue ( events . Any ( e => e . PropertyName == nameof ( Person . Age ) ) ) ;
343
+ }
344
+
345
+ [ TestCategory ( "Mvvm" ) ]
346
+ [ TestMethod ]
347
+ public void Test_ObservableValidator_ValidateAllProperties_WithFallback ( )
348
+ {
349
+ var model = new PersonWithDeferredValidation ( ) ;
350
+ var events = new List < DataErrorsChangedEventArgs > ( ) ;
351
+
352
+ MethodInfo [ ] staticMethods = typeof ( ObservableValidator ) . GetMethods ( BindingFlags . Static | BindingFlags . NonPublic ) ;
353
+ MethodInfo validationMethod = staticMethods . Single ( static m => m . Name . Contains ( "GetValidationActionFallback" ) ) ;
354
+ Func < Type , Action < object > > validationFunc = ( Func < Type , Action < object > > ) validationMethod . CreateDelegate ( typeof ( Func < Type , Action < object > > ) ) ;
355
+ Action < object > validationAction = validationFunc ( model . GetType ( ) ) ;
356
+
357
+ model . ErrorsChanged += ( s , e ) => events . Add ( e ) ;
358
+
359
+ validationAction ( model ) ;
360
+
361
+ Assert . IsTrue ( model . HasErrors ) ;
362
+ Assert . IsTrue ( events . Count == 2 ) ;
363
+
364
+ // Note: we can't use an index here because the order used to return properties
365
+ // from reflection APIs is an implementation detail and might change at any time.
366
+ Assert . IsTrue ( events . Any ( e => e . PropertyName == nameof ( Person . Name ) ) ) ;
367
+ Assert . IsTrue ( events . Any ( e => e . PropertyName == nameof ( Person . Age ) ) ) ;
368
+
369
+ events . Clear ( ) ;
370
+
371
+ model . Name = "James" ;
372
+ model . Age = 42 ;
373
+
374
+ validationAction ( model ) ;
375
+
376
+ Assert . IsFalse ( model . HasErrors ) ;
377
+ Assert . IsTrue ( events . Count == 2 ) ;
378
+ Assert . IsTrue ( events . Any ( e => e . PropertyName == nameof ( Person . Name ) ) ) ;
379
+ Assert . IsTrue ( events . Any ( e => e . PropertyName == nameof ( Person . Age ) ) ) ;
380
+
381
+ events . Clear ( ) ;
382
+
383
+ model . Age = - 10 ;
384
+
385
+ validationAction ( model ) ;
386
+
338
387
Assert . IsTrue ( model . HasErrors ) ;
339
388
Assert . IsTrue ( events . Count == 1 ) ;
340
389
Assert . IsTrue ( events . Any ( e => e . PropertyName == nameof ( Person . Age ) ) ) ;
@@ -414,6 +463,34 @@ public void Test_ObservableValidator_ValidationWithFormattedDisplayName()
414
463
Assert . AreEqual ( allErrors [ 1 ] . ErrorMessage , $ "SECOND: { nameof ( ValidationWithDisplayName . AnotherRequiredField ) } .") ;
415
464
}
416
465
466
+ // See: https://github.com/CommunityToolkit/WindowsCommunityToolkit/issues/4272
467
+ [ TestCategory ( "Mvvm" ) ]
468
+ [ TestMethod ]
469
+ [ DataRow ( typeof ( MyBase ) ) ]
470
+ [ DataRow ( typeof ( MyDerived2 ) ) ]
471
+ public void Test_ObservableRecipient_ValidationOnNonValidatableProperties ( Type type )
472
+ {
473
+ MyBase viewmodel = ( MyBase ) Activator . CreateInstance ( type ) ;
474
+
475
+ viewmodel . ValidateAll ( ) ;
476
+ }
477
+
478
+ // See: https://github.com/CommunityToolkit/WindowsCommunityToolkit/issues/4272
479
+ [ TestCategory ( "Mvvm" ) ]
480
+ [ TestMethod ]
481
+ [ DataRow ( typeof ( MyBase ) ) ]
482
+ [ DataRow ( typeof ( MyDerived2 ) ) ]
483
+ public void Test_ObservableRecipient_ValidationOnNonValidatableProperties_WithFallback ( Type type )
484
+ {
485
+ MyBase viewmodel = ( MyBase ) Activator . CreateInstance ( type ) ;
486
+
487
+ MethodInfo [ ] staticMethods = typeof ( ObservableValidator ) . GetMethods ( BindingFlags . Static | BindingFlags . NonPublic ) ;
488
+ MethodInfo validationMethod = staticMethods . Single ( static m => m . Name . Contains ( "GetValidationActionFallback" ) ) ;
489
+ Func < Type , Action < object > > validationFunc = ( Func < Type , Action < object > > ) validationMethod . CreateDelegate ( typeof ( Func < Type , Action < object > > ) ) ;
490
+
491
+ validationFunc ( viewmodel . GetType ( ) ) ( viewmodel ) ;
492
+ }
493
+
417
494
public class Person : ObservableValidator
418
495
{
419
496
private string name ;
@@ -631,5 +708,22 @@ public string AnotherRequiredField
631
708
set => SetProperty ( ref this . anotherRequiredField , value , true ) ;
632
709
}
633
710
}
711
+
712
+ public class MyBase : ObservableValidator
713
+ {
714
+ public int ? MyDummyInt { get ; set ; } = 0 ;
715
+
716
+ public void ValidateAll ( )
717
+ {
718
+ ValidateAllProperties ( ) ;
719
+ }
720
+ }
721
+
722
+ public class MyDerived2 : MyBase
723
+ {
724
+ public string Name { get ; set ; }
725
+
726
+ public int SomeRandomproperty { get ; set ; }
727
+ }
634
728
}
635
729
}
0 commit comments