AvaloniaObjectTests_SetCurrentValue.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. using System;
  2. using System.Reactive.Concurrency;
  3. using System.Reactive.Subjects;
  4. using Avalonia.Controls;
  5. using Avalonia.Data;
  6. using Avalonia.Diagnostics;
  7. using Avalonia.Styling;
  8. using Avalonia.UnitTests;
  9. using Xunit;
  10. using Observable = Avalonia.Reactive.Observable;
  11. namespace Avalonia.Base.UnitTests
  12. {
  13. public class AvaloniaObjectTests_SetCurrentValue
  14. {
  15. [Fact]
  16. public void SetCurrentValue_Sets_Unset_Value()
  17. {
  18. var target = new Class1();
  19. target.SetCurrentValue(Class1.FooProperty, "newvalue");
  20. Assert.Equal("newvalue", target.GetValue(Class1.FooProperty));
  21. Assert.True(target.IsSet(Class1.FooProperty));
  22. Assert.Equal(BindingPriority.Unset, GetPriority(target, Class1.FooProperty));
  23. Assert.True(IsOverridden(target, Class1.FooProperty));
  24. }
  25. [Fact]
  26. public void SetCurrentValue_Sets_Unset_Value_Untyped()
  27. {
  28. var target = new Class1();
  29. target.SetCurrentValue((AvaloniaProperty)Class1.FooProperty, "newvalue");
  30. Assert.Equal("newvalue", target.GetValue(Class1.FooProperty));
  31. Assert.True(target.IsSet(Class1.FooProperty));
  32. Assert.Equal(BindingPriority.Unset, GetPriority(target, Class1.FooProperty));
  33. Assert.True(IsOverridden(target, Class1.FooProperty));
  34. }
  35. [Theory]
  36. [InlineData(BindingPriority.LocalValue)]
  37. [InlineData(BindingPriority.Style)]
  38. [InlineData(BindingPriority.Animation)]
  39. public void SetCurrentValue_Overrides_Existing_Value(BindingPriority priority)
  40. {
  41. var target = new Class1();
  42. target.SetValue(Class1.FooProperty, "oldvalue", priority);
  43. target.SetCurrentValue(Class1.FooProperty, "newvalue");
  44. Assert.Equal("newvalue", target.GetValue(Class1.FooProperty));
  45. Assert.True(target.IsSet(Class1.FooProperty));
  46. Assert.Equal(priority, GetPriority(target, Class1.FooProperty));
  47. Assert.True(IsOverridden(target, Class1.FooProperty));
  48. }
  49. [Fact]
  50. public void SetCurrentValue_Overrides_Inherited_Value()
  51. {
  52. var parent = new Class1();
  53. var target = new Class1 { InheritanceParent = parent };
  54. parent.SetValue(Class1.InheritedProperty, "inheritedvalue");
  55. target.SetCurrentValue(Class1.InheritedProperty, "newvalue");
  56. Assert.Equal("newvalue", target.GetValue(Class1.InheritedProperty));
  57. Assert.True(target.IsSet(Class1.InheritedProperty));
  58. Assert.Equal(BindingPriority.Unset, GetPriority(target, Class1.InheritedProperty));
  59. Assert.True(IsOverridden(target, Class1.InheritedProperty));
  60. }
  61. [Fact]
  62. public void SetCurrentValue_Is_Inherited()
  63. {
  64. var parent = new Class1();
  65. var target = new Class1 { InheritanceParent = parent };
  66. parent.SetCurrentValue(Class1.InheritedProperty, "newvalue");
  67. Assert.Equal("newvalue", target.GetValue(Class1.InheritedProperty));
  68. Assert.False(target.IsSet(Class1.FooProperty));
  69. Assert.Equal(BindingPriority.Inherited, GetPriority(target, Class1.InheritedProperty));
  70. Assert.False(IsOverridden(target, Class1.InheritedProperty));
  71. }
  72. [Fact]
  73. public void ClearValue_Clears_CurrentValue_With_Unset_Priority()
  74. {
  75. var target = new Class1();
  76. target.SetCurrentValue(Class1.FooProperty, "newvalue");
  77. target.ClearValue(Class1.FooProperty);
  78. Assert.Equal("foodefault", target.Foo);
  79. Assert.False(target.IsSet(Class1.FooProperty));
  80. Assert.False(IsOverridden(target, Class1.FooProperty));
  81. }
  82. [Fact]
  83. public void ClearValue_Clears_CurrentValue_With_Inherited_Priority()
  84. {
  85. var parent = new Class1();
  86. var target = new Class1 { InheritanceParent = parent };
  87. parent.SetValue(Class1.InheritedProperty, "inheritedvalue");
  88. target.SetCurrentValue(Class1.InheritedProperty, "newvalue");
  89. target.ClearValue(Class1.InheritedProperty);
  90. Assert.Equal("inheritedvalue", target.Inherited);
  91. Assert.False(target.IsSet(Class1.FooProperty));
  92. Assert.False(IsOverridden(target, Class1.FooProperty));
  93. }
  94. [Fact]
  95. public void ClearValue_Clears_CurrentValue_With_LocalValue_Priority()
  96. {
  97. var target = new Class1();
  98. target.SetValue(Class1.FooProperty, "localvalue");
  99. target.SetCurrentValue(Class1.FooProperty, "newvalue");
  100. target.ClearValue(Class1.FooProperty);
  101. Assert.Equal("foodefault", target.Foo);
  102. Assert.False(target.IsSet(Class1.FooProperty));
  103. Assert.False(IsOverridden(target, Class1.FooProperty));
  104. }
  105. [Fact]
  106. public void ClearValue_Clears_CurrentValue_With_Style_Priority()
  107. {
  108. var target = new Class1();
  109. target.SetValue(Class1.FooProperty, "stylevalue", BindingPriority.Style);
  110. target.SetCurrentValue(Class1.FooProperty, "newvalue");
  111. target.ClearValue(Class1.FooProperty);
  112. Assert.Equal("stylevalue", target.Foo);
  113. Assert.True(target.IsSet(Class1.FooProperty));
  114. Assert.False(IsOverridden(target, Class1.FooProperty));
  115. }
  116. [Fact]
  117. public void SetCurrentValue_Can_Be_Coerced()
  118. {
  119. var target = new Class1();
  120. target.SetCurrentValue(Class1.CoercedProperty, 60);
  121. Assert.Equal(60, target.GetValue(Class1.CoercedProperty));
  122. target.CoerceMax = 50;
  123. target.CoerceValue(Class1.CoercedProperty);
  124. Assert.Equal(50, target.GetValue(Class1.CoercedProperty));
  125. target.CoerceMax = 100;
  126. target.CoerceValue(Class1.CoercedProperty);
  127. Assert.Equal(60, target.GetValue(Class1.CoercedProperty));
  128. }
  129. [Fact]
  130. public void SetCurrentValue_Unset_Clears_CurrentValue()
  131. {
  132. var target = new Class1();
  133. target.SetCurrentValue(Class1.FooProperty, "newvalue");
  134. target.SetCurrentValue(Class1.FooProperty, AvaloniaProperty.UnsetValue);
  135. Assert.Equal("foodefault", target.Foo);
  136. Assert.False(target.IsSet(Class1.FooProperty));
  137. Assert.False(IsOverridden(target, Class1.FooProperty));
  138. }
  139. [Theory]
  140. [InlineData(BindingPriority.LocalValue)]
  141. [InlineData(BindingPriority.Style)]
  142. [InlineData(BindingPriority.Animation)]
  143. public void SetValue_Overrides_CurrentValue_With_Unset_Priority(BindingPriority priority)
  144. {
  145. var target = new Class1();
  146. target.SetCurrentValue(Class1.FooProperty, "current");
  147. target.SetValue(Class1.FooProperty, "setvalue", priority);
  148. Assert.Equal("setvalue", target.Foo);
  149. Assert.True(target.IsSet(Class1.FooProperty));
  150. Assert.Equal(priority, GetPriority(target, Class1.FooProperty));
  151. Assert.False(IsOverridden(target, Class1.FooProperty));
  152. }
  153. [Fact]
  154. public void Animation_Value_Overrides_CurrentValue_With_LocalValue_Priority()
  155. {
  156. var target = new Class1();
  157. target.SetValue(Class1.FooProperty, "localvalue");
  158. target.SetCurrentValue(Class1.FooProperty, "current");
  159. target.SetValue(Class1.FooProperty, "setvalue", BindingPriority.Animation);
  160. Assert.Equal("setvalue", target.Foo);
  161. Assert.True(target.IsSet(Class1.FooProperty));
  162. Assert.Equal(BindingPriority.Animation, GetPriority(target, Class1.FooProperty));
  163. Assert.False(IsOverridden(target, Class1.FooProperty));
  164. }
  165. [Fact]
  166. public void StyleTrigger_Value_Overrides_CurrentValue_With_Style_Priority()
  167. {
  168. var target = new Class1();
  169. target.SetValue(Class1.FooProperty, "style", BindingPriority.Style);
  170. target.SetCurrentValue(Class1.FooProperty, "current");
  171. target.SetValue(Class1.FooProperty, "setvalue", BindingPriority.StyleTrigger);
  172. Assert.Equal("setvalue", target.Foo);
  173. Assert.True(target.IsSet(Class1.FooProperty));
  174. Assert.Equal(BindingPriority.StyleTrigger, GetPriority(target, Class1.FooProperty));
  175. Assert.False(IsOverridden(target, Class1.FooProperty));
  176. }
  177. [Theory]
  178. [InlineData(BindingPriority.LocalValue)]
  179. [InlineData(BindingPriority.Style)]
  180. [InlineData(BindingPriority.Animation)]
  181. public void Binding_Overrides_CurrentValue_With_Unset_Priority(BindingPriority priority)
  182. {
  183. var target = new Class1();
  184. target.SetCurrentValue(Class1.FooProperty, "current");
  185. var s = target.Bind(Class1.FooProperty, Observable.SingleValue("binding"), priority);
  186. Assert.Equal("binding", target.Foo);
  187. Assert.True(target.IsSet(Class1.FooProperty));
  188. Assert.Equal(priority, GetPriority(target, Class1.FooProperty));
  189. Assert.False(IsOverridden(target, Class1.FooProperty));
  190. s.Dispose();
  191. Assert.Equal("foodefault", target.Foo);
  192. }
  193. [Fact]
  194. public void Animation_Binding_Overrides_CurrentValue_With_LocalValue_Priority()
  195. {
  196. var target = new Class1();
  197. target.SetValue(Class1.FooProperty, "localvalue");
  198. target.SetCurrentValue(Class1.FooProperty, "current");
  199. var s = target.Bind(Class1.FooProperty, Observable.SingleValue("binding"), BindingPriority.Animation);
  200. Assert.Equal("binding", target.Foo);
  201. Assert.True(target.IsSet(Class1.FooProperty));
  202. Assert.Equal(BindingPriority.Animation, GetPriority(target, Class1.FooProperty));
  203. Assert.False(IsOverridden(target, Class1.FooProperty));
  204. s.Dispose();
  205. Assert.Equal("current", target.Foo);
  206. }
  207. [Fact]
  208. public void StyleTrigger_Binding_Overrides_CurrentValue_With_Style_Priority()
  209. {
  210. var target = new Class1();
  211. target.SetValue(Class1.FooProperty, "style", BindingPriority.Style);
  212. target.SetCurrentValue(Class1.FooProperty, "current");
  213. var s = target.Bind(Class1.FooProperty, Observable.SingleValue("binding"), BindingPriority.StyleTrigger);
  214. Assert.Equal("binding", target.Foo);
  215. Assert.True(target.IsSet(Class1.FooProperty));
  216. Assert.Equal(BindingPriority.StyleTrigger, GetPriority(target, Class1.FooProperty));
  217. Assert.False(IsOverridden(target, Class1.FooProperty));
  218. s.Dispose();
  219. Assert.Equal("style", target.Foo);
  220. }
  221. [Fact]
  222. public void SetCurrent_Value_Persists_When_Toggling_Style_1()
  223. {
  224. var target = new Class1();
  225. var root = new TestRoot(target)
  226. {
  227. Styles =
  228. {
  229. new Style(x => x.OfType<Class1>().Class("foo"))
  230. {
  231. Setters = { new Setter(Class1.BarProperty, "bar") },
  232. }
  233. }
  234. };
  235. root.LayoutManager.ExecuteInitialLayoutPass();
  236. target.SetCurrentValue(Class1.FooProperty, "current");
  237. Assert.Equal("current", target.Foo);
  238. Assert.Equal("bardefault", target.Bar);
  239. target.Classes.Add("foo");
  240. Assert.Equal("current", target.Foo);
  241. Assert.Equal("bar", target.Bar);
  242. target.Classes.Remove("foo");
  243. Assert.Equal("current", target.Foo);
  244. Assert.Equal("bardefault", target.Bar);
  245. }
  246. [Fact]
  247. public void SetCurrent_Value_Persists_When_Toggling_Style_2()
  248. {
  249. var target = new Class1();
  250. var root = new TestRoot(target)
  251. {
  252. Styles =
  253. {
  254. new Style(x => x.OfType<Class1>().Class("foo"))
  255. {
  256. Setters =
  257. {
  258. new Setter(Class1.BarProperty, "bar"),
  259. new Setter(Class1.InheritedProperty, "inherited"),
  260. },
  261. }
  262. }
  263. };
  264. root.LayoutManager.ExecuteInitialLayoutPass();
  265. target.SetCurrentValue(Class1.FooProperty, "current");
  266. Assert.Equal("current", target.Foo);
  267. Assert.Equal("bardefault", target.Bar);
  268. Assert.Equal("inheriteddefault", target.Inherited);
  269. target.Classes.Add("foo");
  270. Assert.Equal("current", target.Foo);
  271. Assert.Equal("bar", target.Bar);
  272. Assert.Equal("inherited", target.Inherited);
  273. target.Classes.Remove("foo");
  274. Assert.Equal("current", target.Foo);
  275. Assert.Equal("bardefault", target.Bar);
  276. Assert.Equal("inheriteddefault", target.Inherited);
  277. }
  278. [Fact]
  279. public void SetCurrent_Value_Persists_When_Toggling_Style_3()
  280. {
  281. var target = new Class1();
  282. var root = new TestRoot(target)
  283. {
  284. Styles =
  285. {
  286. new Style(x => x.OfType<Class1>().Class("foo"))
  287. {
  288. Setters =
  289. {
  290. new Setter(Class1.BarProperty, "bar"),
  291. new Setter(Class1.InheritedProperty, "inherited"),
  292. },
  293. }
  294. }
  295. };
  296. root.LayoutManager.ExecuteInitialLayoutPass();
  297. target.SetValue(Class1.FooProperty, "not current", BindingPriority.Template);
  298. target.SetCurrentValue(Class1.FooProperty, "current");
  299. Assert.Equal("current", target.Foo);
  300. Assert.Equal("bardefault", target.Bar);
  301. Assert.Equal("inheriteddefault", target.Inherited);
  302. target.Classes.Add("foo");
  303. Assert.Equal("current", target.Foo);
  304. Assert.Equal("bar", target.Bar);
  305. Assert.Equal("inherited", target.Inherited);
  306. target.Classes.Remove("foo");
  307. Assert.Equal("current", target.Foo);
  308. Assert.Equal("bardefault", target.Bar);
  309. Assert.Equal("inheriteddefault", target.Inherited);
  310. }
  311. [Theory]
  312. [InlineData(BindingPriority.LocalValue)]
  313. [InlineData(BindingPriority.Style)]
  314. [InlineData(BindingPriority.Animation)]
  315. public void CurrentValue_Is_Replaced_By_Binding_Value(BindingPriority priority)
  316. {
  317. var target = new Class1();
  318. var source = new BehaviorSubject<string>("initial");
  319. target.Bind(Class1.FooProperty, source, priority);
  320. target.SetCurrentValue(Class1.FooProperty, "current");
  321. source.OnNext("new");
  322. Assert.Equal("new", target.Foo);
  323. }
  324. [Fact]
  325. public void CurrentValue_Is_Replaced_By_New_Style_Activation_1()
  326. {
  327. var target = new Class1();
  328. var root = new TestRoot(target)
  329. {
  330. Styles =
  331. {
  332. new Style(x => x.OfType<Class1>().Class("foo"))
  333. {
  334. Setters =
  335. {
  336. new Setter(Class1.FooProperty, "initial"),
  337. new Setter(Class1.BarProperty, "bar"),
  338. },
  339. },
  340. new Style(x => x.OfType<Class1>().Class("bar"))
  341. {
  342. Setters =
  343. {
  344. new Setter(Class1.FooProperty, "new"),
  345. new Setter(Class1.BarProperty, "baz"),
  346. },
  347. }, }
  348. };
  349. root.LayoutManager.ExecuteInitialLayoutPass();
  350. target.Classes.Add("foo");
  351. Assert.Equal("initial", target.Foo);
  352. target.SetCurrentValue(Class1.FooProperty, "current");
  353. target.Classes.Add("bar");
  354. Assert.Equal("new", target.Foo);
  355. }
  356. [Fact]
  357. public void CurrentValue_Is_Replaced_By_New_Style_Activation_2()
  358. {
  359. var target = new Class1();
  360. var root = new TestRoot(target)
  361. {
  362. Styles =
  363. {
  364. new Style(x => x.OfType<Class1>().Class("foo"))
  365. {
  366. Setters =
  367. {
  368. new Setter(Class1.FooProperty, "foo"),
  369. },
  370. },
  371. new Style(x => x.OfType<Class1>().Class("foo"))
  372. {
  373. Setters =
  374. {
  375. new Setter(Class1.BarProperty, "bar"),
  376. },
  377. },
  378. }
  379. };
  380. root.LayoutManager.ExecuteInitialLayoutPass();
  381. target.SetValue(Class1.FooProperty, "template", BindingPriority.Template);
  382. target.SetCurrentValue(Class1.FooProperty, "current");
  383. target.Classes.Add("foo");
  384. Assert.Equal("foo", target.Foo);
  385. }
  386. private BindingPriority GetPriority(AvaloniaObject target, AvaloniaProperty property)
  387. {
  388. return target.GetDiagnostic(property).Priority;
  389. }
  390. private bool IsOverridden(AvaloniaObject target, AvaloniaProperty property)
  391. {
  392. return target.GetDiagnostic(property).IsOverriddenCurrentValue;
  393. }
  394. private class Class1 : Control
  395. {
  396. public static readonly StyledProperty<string> FooProperty =
  397. AvaloniaProperty.Register<Class1, string>(nameof(Foo), "foodefault");
  398. public static readonly StyledProperty<string> BarProperty =
  399. AvaloniaProperty.Register<Class1, string>(nameof(Bar), "bardefault");
  400. public static readonly StyledProperty<string> InheritedProperty =
  401. AvaloniaProperty.Register<Class1, string>(nameof(Inherited), "inheriteddefault", inherits: true);
  402. public static readonly StyledProperty<double> CoercedProperty =
  403. AvaloniaProperty.Register<Class1, double>(nameof(Coerced), coerce: Coerce);
  404. public string Foo => GetValue(FooProperty);
  405. public string Bar => GetValue(BarProperty);
  406. public string Inherited => GetValue(InheritedProperty);
  407. public double Coerced => GetValue(CoercedProperty);
  408. public double CoerceMax { get; set; } = 100;
  409. private static double Coerce(AvaloniaObject sender, double value)
  410. {
  411. return Math.Min(value, ((Class1)sender).CoerceMax);
  412. }
  413. }
  414. private class ViewModel : NotifyingBase
  415. {
  416. private string _value;
  417. public string Value
  418. {
  419. get => _value;
  420. set
  421. {
  422. if (_value != value)
  423. {
  424. _value = value;
  425. RaisePropertyChanged();
  426. }
  427. }
  428. }
  429. }
  430. }
  431. }