StyleTests.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. using System;
  2. using System.Collections.Generic;
  3. using Avalonia.Animation;
  4. using Avalonia.Base.UnitTests.Animation;
  5. using Avalonia.Controls;
  6. using Avalonia.Controls.Templates;
  7. using Avalonia.Data;
  8. using Avalonia.Styling;
  9. using Avalonia.UnitTests;
  10. using Moq;
  11. using Xunit;
  12. namespace Avalonia.Base.UnitTests.Styling
  13. {
  14. public class StyleTests
  15. {
  16. [Fact]
  17. public void Style_With_Only_Type_Selector_Should_Update_Value()
  18. {
  19. Style style = new Style(x => x.OfType<Class1>())
  20. {
  21. Setters =
  22. {
  23. new Setter(Class1.FooProperty, "Foo"),
  24. },
  25. };
  26. var target = new Class1();
  27. style.TryAttach(target, null);
  28. Assert.Equal("Foo", target.Foo);
  29. }
  30. [Fact]
  31. public void Style_With_Class_Selector_Should_Update_And_Restore_Value()
  32. {
  33. Style style = new Style(x => x.OfType<Class1>().Class("foo"))
  34. {
  35. Setters =
  36. {
  37. new Setter(Class1.FooProperty, "Foo"),
  38. },
  39. };
  40. var target = new Class1();
  41. style.TryAttach(target, null);
  42. Assert.Equal("foodefault", target.Foo);
  43. target.Classes.Add("foo");
  44. Assert.Equal("Foo", target.Foo);
  45. target.Classes.Remove("foo");
  46. Assert.Equal("foodefault", target.Foo);
  47. }
  48. [Fact]
  49. public void Style_With_No_Selector_Should_Apply_To_Containing_Control()
  50. {
  51. Style style = new Style
  52. {
  53. Setters =
  54. {
  55. new Setter(Class1.FooProperty, "Foo"),
  56. },
  57. };
  58. var target = new Class1();
  59. style.TryAttach(target, target);
  60. Assert.Equal("Foo", target.Foo);
  61. }
  62. [Fact]
  63. public void Should_Throw_For_Selector_With_Trailing_Template_Selector()
  64. {
  65. Assert.Throws<InvalidOperationException>(() =>
  66. new Style(x => x.OfType<Button>().Template()));
  67. }
  68. [Fact]
  69. public void Style_With_No_Selector_Should_Not_Apply_To_Other_Control()
  70. {
  71. Style style = new Style
  72. {
  73. Setters =
  74. {
  75. new Setter(Class1.FooProperty, "Foo"),
  76. },
  77. };
  78. var target = new Class1();
  79. var other = new Class1();
  80. style.TryAttach(target, other);
  81. Assert.Equal("foodefault", target.Foo);
  82. }
  83. [Fact]
  84. public void LocalValue_Should_Override_Style()
  85. {
  86. Style style = new Style(x => x.OfType<Class1>())
  87. {
  88. Setters =
  89. {
  90. new Setter(Class1.FooProperty, "Foo"),
  91. },
  92. };
  93. var target = new Class1
  94. {
  95. Foo = "Original",
  96. };
  97. style.TryAttach(target, null);
  98. Assert.Equal("Original", target.Foo);
  99. }
  100. [Fact]
  101. public void Later_Styles_Should_Override_Earlier()
  102. {
  103. Styles styles = new Styles
  104. {
  105. new Style(x => x.OfType<Class1>().Class("foo"))
  106. {
  107. Setters =
  108. {
  109. new Setter(Class1.FooProperty, "Foo"),
  110. },
  111. },
  112. new Style(x => x.OfType<Class1>().Class("foo"))
  113. {
  114. Setters =
  115. {
  116. new Setter(Class1.FooProperty, "Bar"),
  117. },
  118. }
  119. };
  120. var target = new Class1();
  121. List<string> values = new List<string>();
  122. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  123. styles.TryAttach(target, null);
  124. target.Classes.Add("foo");
  125. target.Classes.Remove("foo");
  126. Assert.Equal(new[] { "foodefault", "Bar", "foodefault" }, values);
  127. }
  128. [Fact]
  129. public void Later_Styles_Should_Override_Earlier_2()
  130. {
  131. Styles styles = new Styles
  132. {
  133. new Style(x => x.OfType<Class1>().Class("foo"))
  134. {
  135. Setters =
  136. {
  137. new Setter(Class1.FooProperty, "Foo"),
  138. },
  139. },
  140. new Style(x => x.OfType<Class1>().Class("bar"))
  141. {
  142. Setters =
  143. {
  144. new Setter(Class1.FooProperty, "Bar"),
  145. },
  146. }
  147. };
  148. var target = new Class1();
  149. List<string> values = new List<string>();
  150. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  151. styles.TryAttach(target, null);
  152. target.Classes.Add("bar");
  153. target.Classes.Add("foo");
  154. target.Classes.Remove("foo");
  155. Assert.Equal(new[] { "foodefault", "Bar" }, values);
  156. }
  157. [Fact]
  158. public void Later_Styles_Should_Override_Earlier_3()
  159. {
  160. Styles styles = new Styles
  161. {
  162. new Style(x => x.OfType<Class1>().Class("foo"))
  163. {
  164. Setters =
  165. {
  166. new Setter(Class1.FooProperty, new Binding("Foo")),
  167. },
  168. },
  169. new Style(x => x.OfType<Class1>().Class("bar"))
  170. {
  171. Setters =
  172. {
  173. new Setter(Class1.FooProperty, new Binding("Bar")),
  174. },
  175. }
  176. };
  177. var target = new Class1
  178. {
  179. DataContext = new
  180. {
  181. Foo = "Foo",
  182. Bar = "Bar",
  183. }
  184. };
  185. List<string> values = new List<string>();
  186. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  187. styles.TryAttach(target, null);
  188. target.Classes.Add("bar");
  189. target.Classes.Add("foo");
  190. target.Classes.Remove("foo");
  191. Assert.Equal(new[] { "foodefault", "Bar" }, values);
  192. }
  193. [Fact]
  194. public void Later_Styles_Should_Override_Earlier_4()
  195. {
  196. Styles styles = new Styles
  197. {
  198. new Style(x => x.OfType<Class1>().Class("foo"))
  199. {
  200. Setters =
  201. {
  202. new Setter(Class1.FooProperty, "foo1"),
  203. },
  204. },
  205. new Style(x => x.OfType<Class1>().Class("foo"))
  206. {
  207. Setters =
  208. {
  209. new Setter(Class1.FooProperty, "foo2"),
  210. new Setter(Class1.DoubleProperty, 123.4),
  211. },
  212. }
  213. };
  214. var target = new Class1();
  215. styles.TryAttach(target, null);
  216. target.Classes.Add("foo");
  217. Assert.Equal("foo2", target.Foo);
  218. Assert.Equal(123.4, target.Double);
  219. }
  220. [Fact]
  221. public void Later_Styles_Should_Override_Earlier_With_Begin_End_Styling()
  222. {
  223. Styles styles = new Styles
  224. {
  225. new Style(x => x.OfType<Class1>().Class("foo"))
  226. {
  227. Setters =
  228. {
  229. new Setter(Class1.FooProperty, "foo1"),
  230. new Setter(Class1.DoubleProperty, 123.4),
  231. },
  232. },
  233. new Style(x => x.OfType<Class1>().Class("foo").Class("bar"))
  234. {
  235. Setters =
  236. {
  237. new Setter(Class1.FooProperty, "foo2"),
  238. },
  239. },
  240. };
  241. var target = new Class1();
  242. target.GetValueStore().BeginStyling();
  243. styles.TryAttach(target, null);
  244. target.GetValueStore().EndStyling();
  245. target.Classes.Add("bar");
  246. target.Classes.Add("foo");
  247. Assert.Equal("foo2", target.Foo);
  248. Assert.Equal(123.4, target.Double);
  249. target.Classes.Remove("foo");
  250. Assert.Equal(0, target.Double);
  251. }
  252. [Fact]
  253. public void Inactive_Values_Should_Not_Be_Made_Active_During_Style_Attach()
  254. {
  255. var root = new TestRoot
  256. {
  257. Styles =
  258. {
  259. new Style(x => x.OfType<Class1>())
  260. {
  261. Setters =
  262. {
  263. new Setter(Class1.FooProperty, "Foo"),
  264. },
  265. },
  266. new Style(x => x.OfType<Class1>())
  267. {
  268. Setters =
  269. {
  270. new Setter(Class1.FooProperty, "Bar"),
  271. },
  272. }
  273. }
  274. };
  275. var values = new List<string>();
  276. var target = new Class1();
  277. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  278. root.Child = target;
  279. Assert.Equal(new[] { "foodefault", "Bar" }, values);
  280. }
  281. [Fact]
  282. public void Inactive_Bindings_Should_Not_Be_Made_Active_During_Style_Attach()
  283. {
  284. var root = new TestRoot
  285. {
  286. Styles =
  287. {
  288. new Style(x => x.OfType<Class1>())
  289. {
  290. Setters =
  291. {
  292. new Setter(Class1.FooProperty, new Binding("Foo")),
  293. },
  294. },
  295. new Style(x => x.OfType<Class1>())
  296. {
  297. Setters =
  298. {
  299. new Setter(Class1.FooProperty, new Binding("Bar")),
  300. },
  301. }
  302. }
  303. };
  304. var values = new List<string>();
  305. var target = new Class1
  306. {
  307. DataContext = new
  308. {
  309. Foo = "Foo",
  310. Bar = "Bar",
  311. }
  312. };
  313. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  314. root.Child = target;
  315. Assert.Equal(new[] { "foodefault", "Bar" }, values);
  316. }
  317. [Fact]
  318. public void Inactive_Values_Should_Not_Be_Made_Active_During_Style_Detach()
  319. {
  320. var root = new TestRoot
  321. {
  322. Styles =
  323. {
  324. new Style(x => x.OfType<Class1>())
  325. {
  326. Setters =
  327. {
  328. new Setter(Class1.FooProperty, "Foo"),
  329. },
  330. },
  331. new Style(x => x.OfType<Class1>())
  332. {
  333. Setters =
  334. {
  335. new Setter(Class1.FooProperty, "Bar"),
  336. },
  337. }
  338. }
  339. };
  340. var target = new Class1();
  341. root.Child = target;
  342. var values = new List<string>();
  343. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  344. root.Child = null;
  345. Assert.Equal(new[] { "Bar", "foodefault" }, values);
  346. }
  347. [Fact]
  348. public void Inactive_Values_Should_Not_Be_Made_Active_During_Style_Detach_2()
  349. {
  350. var root = new TestRoot
  351. {
  352. Styles =
  353. {
  354. new Style(x => x.OfType<Class1>().Class("foo"))
  355. {
  356. Setters =
  357. {
  358. new Setter(Class1.FooProperty, "Foo"),
  359. },
  360. },
  361. new Style(x => x.OfType<Class1>())
  362. {
  363. Setters =
  364. {
  365. new Setter(Class1.FooProperty, "Bar"),
  366. },
  367. }
  368. }
  369. };
  370. var target = new Class1 { Classes = { "foo" } };
  371. root.Child = target;
  372. var values = new List<string>();
  373. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  374. root.Child = null;
  375. Assert.Equal(new[] { "Foo", "foodefault" }, values);
  376. }
  377. [Fact]
  378. public void Inactive_Bindings_Should_Not_Be_Made_Active_During_Style_Detach()
  379. {
  380. var root = new TestRoot
  381. {
  382. Styles =
  383. {
  384. new Style(x => x.OfType<Class1>())
  385. {
  386. Setters =
  387. {
  388. new Setter(Class1.FooProperty, new Binding("Foo")),
  389. },
  390. },
  391. new Style(x => x.OfType<Class1>())
  392. {
  393. Setters =
  394. {
  395. new Setter(Class1.FooProperty, new Binding("Bar")),
  396. },
  397. }
  398. }
  399. };
  400. var target = new Class1
  401. {
  402. DataContext = new
  403. {
  404. Foo = "Foo",
  405. Bar = "Bar",
  406. }
  407. };
  408. root.Child = target;
  409. var values = new List<string>();
  410. target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x));
  411. root.Child = null;
  412. Assert.Equal(new[] { "Bar", "foodefault" }, values);
  413. }
  414. [Fact]
  415. public void Template_In_Non_Matching_Style_Is_Not_Built()
  416. {
  417. var instantiationCount = 0;
  418. var template = new FuncTemplate<Class1>(() =>
  419. {
  420. ++instantiationCount;
  421. return new Class1();
  422. });
  423. Styles styles = new Styles
  424. {
  425. new Style(x => x.OfType<Class1>().Class("foo"))
  426. {
  427. Setters =
  428. {
  429. new Setter(Class1.ChildProperty, template),
  430. },
  431. },
  432. new Style(x => x.OfType<Class1>())
  433. {
  434. Setters =
  435. {
  436. new Setter(Class1.ChildProperty, template),
  437. },
  438. }
  439. };
  440. var target = new Class1();
  441. styles.TryAttach(target, null);
  442. Assert.NotNull(target.Child);
  443. Assert.Equal(1, instantiationCount);
  444. }
  445. [Fact]
  446. public void Template_In_Inactive_Style_Is_Not_Built()
  447. {
  448. var instantiationCount = 0;
  449. var template = new FuncTemplate<Class1>(() =>
  450. {
  451. ++instantiationCount;
  452. return new Class1();
  453. });
  454. Styles styles = new Styles
  455. {
  456. new Style(x => x.OfType<Class1>())
  457. {
  458. Setters =
  459. {
  460. new Setter(Class1.ChildProperty, template),
  461. },
  462. },
  463. new Style(x => x.OfType<Class1>())
  464. {
  465. Setters =
  466. {
  467. new Setter(Class1.ChildProperty, template),
  468. },
  469. }
  470. };
  471. var target = new Class1();
  472. target.GetValueStore().BeginStyling();
  473. styles.TryAttach(target, null);
  474. target.GetValueStore().EndStyling();
  475. Assert.NotNull(target.Child);
  476. Assert.Equal(1, instantiationCount);
  477. }
  478. [Fact]
  479. public void Style_Should_Detach_When_Control_Removed_From_Logical_Tree()
  480. {
  481. Border border;
  482. var style = new Style(x => x.OfType<Border>())
  483. {
  484. Setters =
  485. {
  486. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  487. }
  488. };
  489. var root = new TestRoot
  490. {
  491. Child = border = new Border(),
  492. };
  493. style.TryAttach(border, null);
  494. Assert.Equal(new Thickness(4), border.BorderThickness);
  495. root.Child = null;
  496. Assert.Equal(new Thickness(0), border.BorderThickness);
  497. }
  498. [Fact]
  499. public void Removing_Style_Should_Detach_From_Control()
  500. {
  501. var border = new Border();
  502. var root = new TestRoot
  503. {
  504. Styles =
  505. {
  506. new Style(x => x.OfType<Border>())
  507. {
  508. Setters =
  509. {
  510. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  511. }
  512. }
  513. },
  514. Child = border,
  515. };
  516. root.Measure(Size.Infinity);
  517. Assert.Equal(new Thickness(4), border.BorderThickness);
  518. root.Styles.RemoveAt(0);
  519. Assert.Equal(new Thickness(0), border.BorderThickness);
  520. }
  521. [Fact]
  522. public void Adding_Style_Should_Attach_To_Control()
  523. {
  524. var border = new Border();
  525. var root = new TestRoot
  526. {
  527. Styles =
  528. {
  529. new Style(x => x.OfType<Border>())
  530. {
  531. Setters =
  532. {
  533. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  534. }
  535. }
  536. },
  537. Child = border,
  538. };
  539. root.Measure(Size.Infinity);
  540. Assert.Equal(new Thickness(4), border.BorderThickness);
  541. root.Styles.Add(new Style(x => x.OfType<Border>())
  542. {
  543. Setters =
  544. {
  545. new Setter(Border.BorderThicknessProperty, new Thickness(6)),
  546. }
  547. });
  548. root.Measure(Size.Infinity);
  549. Assert.Equal(new Thickness(6), border.BorderThickness);
  550. }
  551. [Fact]
  552. public void Removing_Style_With_Nested_Style_Should_Detach_From_Control()
  553. {
  554. var border = new Border();
  555. var root = new TestRoot
  556. {
  557. Styles =
  558. {
  559. new Styles
  560. {
  561. new Style(x => x.OfType<Border>())
  562. {
  563. Setters =
  564. {
  565. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  566. }
  567. }
  568. }
  569. },
  570. Child = border,
  571. };
  572. root.Measure(Size.Infinity);
  573. Assert.Equal(new Thickness(4), border.BorderThickness);
  574. root.Styles.RemoveAt(0);
  575. Assert.Equal(new Thickness(0), border.BorderThickness);
  576. }
  577. [Fact]
  578. public void Adding_Nested_Style_Should_Attach_To_Control()
  579. {
  580. var border = new Border();
  581. var root = new TestRoot
  582. {
  583. Styles =
  584. {
  585. new Styles
  586. {
  587. new Style(x => x.OfType<Border>())
  588. {
  589. Setters =
  590. {
  591. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  592. }
  593. }
  594. }
  595. },
  596. Child = border,
  597. };
  598. root.Measure(Size.Infinity);
  599. Assert.Equal(new Thickness(4), border.BorderThickness);
  600. ((Styles)root.Styles[0]).Add(new Style(x => x.OfType<Border>())
  601. {
  602. Setters =
  603. {
  604. new Setter(Border.BorderThicknessProperty, new Thickness(6)),
  605. }
  606. });
  607. root.Measure(Size.Infinity);
  608. Assert.Equal(new Thickness(6), border.BorderThickness);
  609. }
  610. [Fact]
  611. public void Removing_Nested_Style_Should_Detach_From_Control()
  612. {
  613. var border = new Border();
  614. var root = new TestRoot
  615. {
  616. Styles =
  617. {
  618. new Styles
  619. {
  620. new Style(x => x.OfType<Border>())
  621. {
  622. Setters =
  623. {
  624. new Setter(Border.BorderThicknessProperty, new Thickness(4)),
  625. }
  626. },
  627. new Style(x => x.OfType<Border>())
  628. {
  629. Setters =
  630. {
  631. new Setter(Border.BorderThicknessProperty, new Thickness(6)),
  632. }
  633. },
  634. }
  635. },
  636. Child = border,
  637. };
  638. root.Measure(Size.Infinity);
  639. Assert.Equal(new Thickness(6), border.BorderThickness);
  640. ((Styles)root.Styles[0]).RemoveAt(1);
  641. root.Measure(Size.Infinity);
  642. Assert.Equal(new Thickness(4), border.BorderThickness);
  643. }
  644. [Fact]
  645. public void DetachStyles_Should_Detach_Activator()
  646. {
  647. Style style = new Style(x => x.OfType<Class1>().Class("foo"))
  648. {
  649. Setters =
  650. {
  651. new Setter(Class1.FooProperty, "Foo"),
  652. },
  653. };
  654. var target = new Class1();
  655. style.TryAttach(target, null);
  656. Assert.Equal(1, target.Classes.ListenerCount);
  657. ((IStyleable)target).DetachStyles();
  658. Assert.Equal(0, target.Classes.ListenerCount);
  659. }
  660. [Fact]
  661. public void Should_Set_Owner_On_Assigned_Resources()
  662. {
  663. var host = new Mock<IResourceHost>();
  664. var target = new Style();
  665. ((IResourceProvider)target).AddOwner(host.Object);
  666. var resources = new Mock<IResourceDictionary>();
  667. target.Resources = resources.Object;
  668. resources.Verify(x => x.AddOwner(host.Object), Times.Once);
  669. }
  670. [Fact]
  671. public void Should_Set_Owner_On_Assigned_Resources_2()
  672. {
  673. var host = new Mock<IResourceHost>();
  674. var target = new Style();
  675. var resources = new Mock<IResourceDictionary>();
  676. target.Resources = resources.Object;
  677. host.Invocations.Clear();
  678. ((IResourceProvider)target).AddOwner(host.Object);
  679. resources.Verify(x => x.AddOwner(host.Object), Times.Once);
  680. }
  681. [Fact]
  682. public void Nested_Style_Can_Be_Added()
  683. {
  684. var parent = new Style(x => x.OfType<Class1>());
  685. var nested = new Style(x => x.Nesting().Class("foo"));
  686. parent.Children.Add(nested);
  687. Assert.Same(parent, nested.Parent);
  688. }
  689. [Fact]
  690. public void Nested_Or_Style_Can_Be_Added()
  691. {
  692. var parent = new Style(x => x.OfType<Class1>());
  693. var nested = new Style(x => Selectors.Or(
  694. x.Nesting().Class("foo"),
  695. x.Nesting().Class("bar")));
  696. parent.Children.Add(nested);
  697. Assert.Same(parent, nested.Parent);
  698. }
  699. [Fact]
  700. public void Nested_Style_Without_Selector_Throws()
  701. {
  702. var parent = new Style(x => x.OfType<Class1>());
  703. var nested = new Style();
  704. Assert.Throws<InvalidOperationException>(() => parent.Children.Add(nested));
  705. }
  706. [Fact(Skip = "TODO")]
  707. public void Nested_Style_Without_Nesting_Operator_Throws()
  708. {
  709. var parent = new Style(x => x.OfType<Class1>());
  710. var nested = new Style(x => x.Class("foo"));
  711. Assert.Throws<InvalidOperationException>(() => parent.Children.Add(nested));
  712. }
  713. [Fact]
  714. public void Animations_Should_Be_Activated_And_Deactivated()
  715. {
  716. Style style = new Style(x => x.OfType<Class1>().Class("foo"))
  717. {
  718. Animations =
  719. {
  720. new Avalonia.Animation.Animation
  721. {
  722. Duration = TimeSpan.FromSeconds(1),
  723. Children =
  724. {
  725. new KeyFrame
  726. {
  727. Setters =
  728. {
  729. new Setter { Property = Class1.DoubleProperty, Value = 5.0 }
  730. },
  731. },
  732. new KeyFrame
  733. {
  734. Setters =
  735. {
  736. new Setter { Property = Class1.DoubleProperty, Value = 10.0 }
  737. },
  738. Cue = new Cue(1d)
  739. }
  740. },
  741. }
  742. }
  743. };
  744. var clock = new TestClock();
  745. var target = new Class1 { Clock = clock };
  746. style.TryAttach(target, null);
  747. Assert.Equal(0.0, target.Double);
  748. target.Classes.Add("foo");
  749. clock.Step(TimeSpan.Zero);
  750. Assert.Equal(5.0, target.Double);
  751. clock.Step(TimeSpan.FromSeconds(0.5));
  752. Assert.Equal(7.5, target.Double);
  753. target.Classes.Remove("foo");
  754. Assert.Equal(0.0, target.Double);
  755. }
  756. private class Class1 : Control
  757. {
  758. public static readonly StyledProperty<string> FooProperty =
  759. AvaloniaProperty.Register<Class1, string>(nameof(Foo), "foodefault");
  760. public static readonly StyledProperty<Class1> ChildProperty =
  761. AvaloniaProperty.Register<Class1, Class1>(nameof(Child));
  762. public static readonly StyledProperty<double> DoubleProperty =
  763. AvaloniaProperty.Register<Class1, double>(nameof(Double));
  764. public string Foo
  765. {
  766. get { return GetValue(FooProperty); }
  767. set { SetValue(FooProperty, value); }
  768. }
  769. public Class1 Child
  770. {
  771. get => GetValue(ChildProperty);
  772. set => SetValue(ChildProperty, value);
  773. }
  774. public double Double
  775. {
  776. get => GetValue(DoubleProperty);
  777. set => SetValue(DoubleProperty, value);
  778. }
  779. protected override Size MeasureOverride(Size availableSize)
  780. {
  781. throw new NotImplementedException();
  782. }
  783. }
  784. }
  785. }