AvaloniaObjectTests_DataValidation.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reactive.Subjects;
  5. using Avalonia.Data;
  6. using Avalonia.UnitTests;
  7. using Xunit;
  8. namespace Avalonia.Base.UnitTests
  9. {
  10. public class AvaloniaObjectTests_DataValidation
  11. {
  12. [Fact]
  13. public void Binding_Non_Validated_Styled_Property_Does_Not_Call_UpdateDataValidation()
  14. {
  15. var target = new Class1();
  16. var source = new Subject<BindingValue<int>>();
  17. target.Bind(Class1.NonValidatedProperty, source);
  18. source.OnNext(6);
  19. source.OnNext(BindingValue<int>.BindingError(new Exception()));
  20. source.OnNext(BindingValue<int>.DataValidationError(new Exception()));
  21. source.OnNext(6);
  22. Assert.Empty(target.Notifications);
  23. }
  24. [Fact]
  25. public void Binding_Non_Validated_Direct_Property_Does_Not_Call_UpdateDataValidation()
  26. {
  27. var target = new Class1();
  28. var source = new Subject<BindingValue<int>>();
  29. target.Bind(Class1.NonValidatedDirectProperty, source);
  30. source.OnNext(6);
  31. source.OnNext(BindingValue<int>.BindingError(new Exception()));
  32. source.OnNext(BindingValue<int>.DataValidationError(new Exception()));
  33. source.OnNext(6);
  34. Assert.Empty(target.Notifications);
  35. }
  36. [Fact]
  37. public void Binding_Validated_Direct_Property_Calls_UpdateDataValidation()
  38. {
  39. var target = new Class1();
  40. var source = new Subject<BindingValue<int>>();
  41. target.Bind(Class1.ValidatedDirectIntProperty, source);
  42. source.OnNext(6);
  43. source.OnNext(BindingValue<int>.BindingError(new Exception()));
  44. source.OnNext(BindingValue<int>.DataValidationError(new Exception()));
  45. source.OnNext(7);
  46. var result = target.Notifications.Cast<BindingValue<int>>().ToList();
  47. Assert.Equal(4, result.Count);
  48. Assert.Equal(BindingValueType.Value, result[0].Type);
  49. Assert.Equal(6, result[0].Value);
  50. Assert.Equal(BindingValueType.BindingError, result[1].Type);
  51. Assert.Equal(BindingValueType.DataValidationError, result[2].Type);
  52. Assert.Equal(BindingValueType.Value, result[3].Type);
  53. Assert.Equal(7, result[3].Value);
  54. }
  55. [Fact]
  56. public void Binding_Overridden_Validated_Direct_Property_Calls_UpdateDataValidation()
  57. {
  58. var target = new Class2();
  59. var source = new Subject<BindingValue<int>>();
  60. // Class2 overrides `NonValidatedDirectProperty`'s metadata to enable data validation.
  61. target.Bind(Class1.NonValidatedDirectProperty, source);
  62. source.OnNext(1);
  63. var result = target.Notifications.Cast<BindingValue<int>>().ToList();
  64. Assert.Equal(1, result.Count);
  65. }
  66. [Fact]
  67. public void Bound_Validated_Direct_String_Property_Can_Be_Set_To_Null()
  68. {
  69. var source = new ViewModel
  70. {
  71. StringValue = "foo",
  72. };
  73. var target = new Class1
  74. {
  75. [!Class1.ValidatedDirectStringProperty] = new Binding
  76. {
  77. Path = nameof(ViewModel.StringValue),
  78. Source = source,
  79. },
  80. };
  81. Assert.Equal("foo", target.ValidatedDirectString);
  82. source.StringValue = null;
  83. Assert.Null(target.ValidatedDirectString);
  84. }
  85. private class Class1 : AvaloniaObject
  86. {
  87. public static readonly StyledProperty<int> NonValidatedProperty =
  88. AvaloniaProperty.Register<Class1, int>(
  89. nameof(NonValidated));
  90. public static readonly DirectProperty<Class1, int> NonValidatedDirectProperty =
  91. AvaloniaProperty.RegisterDirect<Class1, int>(
  92. nameof(NonValidatedDirect),
  93. o => o.NonValidatedDirect,
  94. (o, v) => o.NonValidatedDirect = v);
  95. public static readonly DirectProperty<Class1, int> ValidatedDirectIntProperty =
  96. AvaloniaProperty.RegisterDirect<Class1, int>(
  97. nameof(ValidatedDirectInt),
  98. o => o.ValidatedDirectInt,
  99. (o, v) => o.ValidatedDirectInt = v,
  100. enableDataValidation: true);
  101. public static readonly DirectProperty<Class1, string> ValidatedDirectStringProperty =
  102. AvaloniaProperty.RegisterDirect<Class1, string>(
  103. nameof(ValidatedDirectString),
  104. o => o.ValidatedDirectString,
  105. (o, v) => o.ValidatedDirectString = v,
  106. enableDataValidation: true);
  107. private int _nonValidatedDirect;
  108. private int _directInt;
  109. private string _directString;
  110. public int NonValidated
  111. {
  112. get { return GetValue(NonValidatedProperty); }
  113. set { SetValue(NonValidatedProperty, value); }
  114. }
  115. public int NonValidatedDirect
  116. {
  117. get { return _directInt; }
  118. set { SetAndRaise(NonValidatedDirectProperty, ref _nonValidatedDirect, value); }
  119. }
  120. public int ValidatedDirectInt
  121. {
  122. get { return _directInt; }
  123. set { SetAndRaise(ValidatedDirectIntProperty, ref _directInt, value); }
  124. }
  125. public string ValidatedDirectString
  126. {
  127. get { return _directString; }
  128. set { SetAndRaise(ValidatedDirectStringProperty, ref _directString, value); }
  129. }
  130. public IList<object> Notifications { get; } = new List<object>();
  131. protected override void UpdateDataValidation<T>(
  132. AvaloniaProperty<T> property,
  133. BindingValue<T> value)
  134. {
  135. Notifications.Add(value);
  136. }
  137. }
  138. private class Class2 : Class1
  139. {
  140. static Class2()
  141. {
  142. NonValidatedDirectProperty.OverrideMetadata<Class2>(
  143. new DirectPropertyMetadata<int>(enableDataValidation: true));
  144. }
  145. }
  146. public class ViewModel : NotifyingBase
  147. {
  148. private string _stringValue;
  149. public string StringValue
  150. {
  151. get { return _stringValue; }
  152. set { _stringValue = value; RaisePropertyChanged(); }
  153. }
  154. }
  155. }
  156. }