BindingTests_Validation.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using Avalonia.Controls;
  5. using Avalonia.Data;
  6. using Avalonia.Markup.Xaml.Data;
  7. using Avalonia.UnitTests;
  8. using Xunit;
  9. namespace Avalonia.Markup.Xaml.UnitTests.Data
  10. {
  11. public class BindingTests_Validation
  12. {
  13. [Fact]
  14. public void Non_Validated_Property_Does_Not_Receive_BindingNotifications()
  15. {
  16. var source = new ValidationTestModel { MustBePositive = 5 };
  17. var target = new TestControl
  18. {
  19. DataContext = source,
  20. [!TestControl.NonValidatedProperty] = new Binding(nameof(source.MustBePositive)),
  21. };
  22. Assert.Empty(target.Notifications);
  23. }
  24. [Fact]
  25. public void Validated_Property_Does_Not_Receive_BindingNotifications()
  26. {
  27. var source = new ValidationTestModel { MustBePositive = 5 };
  28. var target = new TestControl
  29. {
  30. DataContext = source,
  31. [!TestControl.ValidatedProperty] = new Binding(nameof(source.MustBePositive)),
  32. };
  33. source.MustBePositive = 6;
  34. Assert.Equal(
  35. new[]
  36. {
  37. new BindingNotification(5),
  38. new BindingNotification(new ArgumentOutOfRangeException("value"), BindingErrorType.DataValidationError),
  39. new BindingNotification(6),
  40. },
  41. target.Notifications);
  42. }
  43. //[Fact]
  44. //public void Disabled_Validation_Should_Trigger_Validation_Change_On_Exception()
  45. //{
  46. // var source = new ValidationTestModel { MustBePositive = 5 };
  47. // var target = new TestControl { DataContext = source };
  48. // var binding = new Binding
  49. // {
  50. // Path = nameof(source.MustBePositive),
  51. // Mode = BindingMode.TwoWay,
  52. // // Even though EnableValidation = false, exception validation is enabled.
  53. // EnableValidation = false,
  54. // };
  55. // target.Bind(TestControl.ValidationTestProperty, binding);
  56. // target.ValidationTest = -5;
  57. // Assert.True(false);
  58. // //Assert.False(target.ValidationStatus.IsValid);
  59. //}
  60. //[Fact]
  61. //public void Enabled_Validation_Should_Trigger_Validation_Change_On_Exception()
  62. //{
  63. // var source = new ValidationTestModel { MustBePositive = 5 };
  64. // var target = new TestControl { DataContext = source };
  65. // var binding = new Binding
  66. // {
  67. // Path = nameof(source.MustBePositive),
  68. // Mode = BindingMode.TwoWay,
  69. // EnableValidation = true,
  70. // };
  71. // target.Bind(TestControl.ValidationTestProperty, binding);
  72. // target.ValidationTest = -5;
  73. // Assert.True(false);
  74. // //Assert.False(target.ValidationStatus.IsValid);
  75. //}
  76. //[Fact]
  77. //public void Passed_Validation_Should_Not_Add_Invalid_Pseudo_Class()
  78. //{
  79. // var control = new TestControl();
  80. // var model = new ValidationTestModel { MustBePositive = 1 };
  81. // var binding = new Binding
  82. // {
  83. // Path = nameof(model.MustBePositive),
  84. // Mode = BindingMode.TwoWay,
  85. // EnableValidation = true,
  86. // };
  87. // control.Bind(TestControl.ValidationTestProperty, binding);
  88. // control.DataContext = model;
  89. // Assert.DoesNotContain(control.Classes, x => x == ":invalid");
  90. //}
  91. //[Fact]
  92. //public void Failed_Validation_Should_Add_Invalid_Pseudo_Class()
  93. //{
  94. // var control = new TestControl();
  95. // var model = new ValidationTestModel { MustBePositive = 1 };
  96. // var binding = new Binding
  97. // {
  98. // Path = nameof(model.MustBePositive),
  99. // Mode = BindingMode.TwoWay,
  100. // EnableValidation = true,
  101. // };
  102. // control.Bind(TestControl.ValidationTestProperty, binding);
  103. // control.DataContext = model;
  104. // control.ValidationTest = -5;
  105. // Assert.Contains(control.Classes, x => x == ":invalid");
  106. //}
  107. //[Fact]
  108. //public void Failed_Then_Passed_Validation_Should_Remove_Invalid_Pseudo_Class()
  109. //{
  110. // var control = new TestControl();
  111. // var model = new ValidationTestModel { MustBePositive = 1 };
  112. // var binding = new Binding
  113. // {
  114. // Path = nameof(model.MustBePositive),
  115. // Mode = BindingMode.TwoWay,
  116. // EnableValidation = true,
  117. // };
  118. // control.Bind(TestControl.ValidationTestProperty, binding);
  119. // control.DataContext = model;
  120. // control.ValidationTest = -5;
  121. // Assert.Contains(control.Classes, x => x == ":invalid");
  122. // control.ValidationTest = 5;
  123. // Assert.DoesNotContain(control.Classes, x => x == ":invalid");
  124. //}
  125. private class TestControl : Control
  126. {
  127. public static readonly StyledProperty<int> NonValidatedProperty =
  128. AvaloniaProperty.Register<TestControl, int>(
  129. nameof(Validated),
  130. enableDataValidation: false);
  131. public static readonly StyledProperty<int> ValidatedProperty =
  132. AvaloniaProperty.Register<TestControl, int>(
  133. nameof(Validated),
  134. enableDataValidation: true);
  135. public int NonValidated
  136. {
  137. get { return GetValue(NonValidatedProperty); }
  138. set { SetValue(NonValidatedProperty, value); }
  139. }
  140. public int Validated
  141. {
  142. get { return GetValue(ValidatedProperty); }
  143. set { SetValue(ValidatedProperty, value); }
  144. }
  145. public IList<BindingNotification> Notifications { get; } = new List<BindingNotification>();
  146. protected override void BindingNotificationReceived(AvaloniaProperty property, BindingNotification notification)
  147. {
  148. Notifications.Add(notification);
  149. }
  150. }
  151. private class ValidationTestModel : NotifyingBase
  152. {
  153. private int mustBePositive;
  154. public int MustBePositive
  155. {
  156. get { return mustBePositive; }
  157. set
  158. {
  159. if (value <= 0)
  160. {
  161. throw new ArgumentOutOfRangeException(nameof(value));
  162. }
  163. mustBePositive = value;
  164. RaisePropertyChanged();
  165. }
  166. }
  167. }
  168. }
  169. }