DynamicResourceExtensionTests.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. using System;
  2. using System.Linq;
  3. using Avalonia.Controls;
  4. using Avalonia.Controls.Presenters;
  5. using Avalonia.Controls.Templates;
  6. using Avalonia.Markup.Data;
  7. using Avalonia.Media;
  8. using Avalonia.Styling;
  9. using Avalonia.UnitTests;
  10. using Avalonia.VisualTree;
  11. using Xunit;
  12. namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
  13. {
  14. public class DynamicResourceExtensionTests : XamlTestBase
  15. {
  16. [Fact]
  17. public void DynamicResource_Can_Be_Assigned_To_Property()
  18. {
  19. var xaml = @"
  20. <UserControl xmlns='https://github.com/avaloniaui'
  21. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  22. <UserControl.Resources>
  23. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  24. </UserControl.Resources>
  25. <Border Name='border' Background='{DynamicResource brush}'/>
  26. </UserControl>";
  27. var loader = new AvaloniaXamlLoader();
  28. var userControl = (UserControl)loader.Load(xaml);
  29. var border = userControl.FindControl<Border>("border");
  30. DelayedBinding.ApplyBindings(border);
  31. var brush = (SolidColorBrush)border.Background;
  32. Assert.Equal(0xff506070, brush.Color.ToUint32());
  33. }
  34. [Fact]
  35. public void DynamicResource_Can_Be_Assigned_To_Attached_Property()
  36. {
  37. var xaml = @"
  38. <UserControl xmlns='https://github.com/avaloniaui'
  39. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  40. <UserControl.Resources>
  41. <x:Int32 x:Key='col'>5</x:Int32>
  42. </UserControl.Resources>
  43. <Border Name='border' Grid.Column='{DynamicResource col}'/>
  44. </UserControl>";
  45. var loader = new AvaloniaXamlLoader();
  46. var userControl = (UserControl)loader.Load(xaml);
  47. var border = userControl.FindControl<Border>("border");
  48. DelayedBinding.ApplyBindings(border);
  49. Assert.Equal(5, Grid.GetColumn(border));
  50. }
  51. [Fact]
  52. public void DynamicResource_From_Style_Can_Be_Assigned_To_Property()
  53. {
  54. var xaml = @"
  55. <UserControl xmlns='https://github.com/avaloniaui'
  56. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  57. <UserControl.Styles>
  58. <Style>
  59. <Style.Resources>
  60. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  61. </Style.Resources>
  62. </Style>
  63. </UserControl.Styles>
  64. <Border Name='border' Background='{DynamicResource brush}'/>
  65. </UserControl>";
  66. var loader = new AvaloniaXamlLoader();
  67. var userControl = (UserControl)loader.Load(xaml);
  68. var border = userControl.FindControl<Border>("border");
  69. DelayedBinding.ApplyBindings(border);
  70. var brush = (SolidColorBrush)border.Background;
  71. Assert.Equal(0xff506070, brush.Color.ToUint32());
  72. }
  73. [Fact]
  74. public void DynamicResource_From_MergedDictionary_Can_Be_Assigned_To_Property()
  75. {
  76. var xaml = @"
  77. <UserControl xmlns='https://github.com/avaloniaui'
  78. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  79. <UserControl.Resources>
  80. <ResourceDictionary>
  81. <ResourceDictionary.MergedDictionaries>
  82. <ResourceDictionary>
  83. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  84. </ResourceDictionary>
  85. </ResourceDictionary.MergedDictionaries>
  86. </ResourceDictionary>
  87. </UserControl.Resources>
  88. <Border Name='border' Background='{DynamicResource brush}'/>
  89. </UserControl>";
  90. var loader = new AvaloniaXamlLoader();
  91. var userControl = (UserControl)loader.Load(xaml);
  92. var border = userControl.FindControl<Border>("border");
  93. DelayedBinding.ApplyBindings(border);
  94. var brush = (SolidColorBrush)border.Background;
  95. Assert.Equal(0xff506070, brush.Color.ToUint32());
  96. }
  97. [Fact]
  98. public void DynamicResource_From_MergedDictionary_In_Style_Can_Be_Assigned_To_Property()
  99. {
  100. var xaml = @"
  101. <UserControl xmlns='https://github.com/avaloniaui'
  102. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  103. <UserControl.Styles>
  104. <Style>
  105. <Style.Resources>
  106. <ResourceDictionary>
  107. <ResourceDictionary.MergedDictionaries>
  108. <ResourceDictionary>
  109. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  110. </ResourceDictionary>
  111. </ResourceDictionary.MergedDictionaries>
  112. </ResourceDictionary>
  113. </Style.Resources>
  114. </Style>
  115. </UserControl.Styles>
  116. <Border Name='border' Background='{DynamicResource brush}'/>
  117. </UserControl>";
  118. var loader = new AvaloniaXamlLoader();
  119. var userControl = (UserControl)loader.Load(xaml);
  120. var border = userControl.FindControl<Border>("border");
  121. DelayedBinding.ApplyBindings(border);
  122. var brush = (SolidColorBrush)border.Background;
  123. Assert.Equal(0xff506070, brush.Color.ToUint32());
  124. }
  125. [Fact]
  126. public void DynamicResource_From_Application_Can_Be_Assigned_To_Property_In_Window()
  127. {
  128. using (StyledWindow())
  129. {
  130. Application.Current.Resources.Add("brush", new SolidColorBrush(0xff506070));
  131. var xaml = @"
  132. <Window xmlns='https://github.com/avaloniaui'
  133. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  134. <Border Name='border' Background='{DynamicResource brush}'/>
  135. </Window>";
  136. var loader = new AvaloniaXamlLoader();
  137. var window = (Window)loader.Load(xaml);
  138. var border = window.FindControl<Border>("border");
  139. var brush = (SolidColorBrush)border.Background;
  140. Assert.Equal(0xff506070, brush.Color.ToUint32());
  141. }
  142. }
  143. [Fact]
  144. public void DynamicResource_From_Application_Can_Be_Assigned_To_Property_In_UserControl()
  145. {
  146. using (UnitTestApplication.Start(TestServices.StyledWindow))
  147. {
  148. Application.Current.Resources.Add("brush", new SolidColorBrush(0xff506070));
  149. var xaml = @"
  150. <UserControl xmlns='https://github.com/avaloniaui'
  151. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  152. <Border Name='border' Background='{DynamicResource brush}'/>
  153. </UserControl>";
  154. var loader = new AvaloniaXamlLoader();
  155. var userControl = (UserControl)loader.Load(xaml);
  156. var border = userControl.FindControl<Border>("border");
  157. // We don't actually know where the global styles are until we attach the control
  158. // to a window, as Window has StylingParent set to Application.
  159. var window = new Window { Content = userControl };
  160. window.Show();
  161. var brush = (SolidColorBrush)border.Background;
  162. Assert.Equal(0xff506070, brush.Color.ToUint32());
  163. }
  164. }
  165. [Fact]
  166. public void DynamicResource_Can_Be_Assigned_To_Setter()
  167. {
  168. using (StyledWindow())
  169. {
  170. var xaml = @"
  171. <Window xmlns='https://github.com/avaloniaui'
  172. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  173. <Window.Resources>
  174. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  175. </Window.Resources>
  176. <Window.Styles>
  177. <Style Selector='Button'>
  178. <Setter Property='Background' Value='{DynamicResource brush}'/>
  179. </Style>
  180. </Window.Styles>
  181. <Button Name='button'/>
  182. </Window>";
  183. var loader = new AvaloniaXamlLoader();
  184. var window = (Window)loader.Load(xaml);
  185. var button = window.FindControl<Button>("button");
  186. var brush = (SolidColorBrush)button.Background;
  187. Assert.Equal(0xff506070, brush.Color.ToUint32());
  188. }
  189. }
  190. [Fact]
  191. public void DynamicResource_From_Style_Can_Be_Assigned_To_Setter()
  192. {
  193. using (StyledWindow())
  194. {
  195. var xaml = @"
  196. <Window xmlns='https://github.com/avaloniaui'
  197. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  198. <Window.Styles>
  199. <Style>
  200. <Style.Resources>
  201. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  202. </Style.Resources>
  203. </Style>
  204. <Style Selector='Button'>
  205. <Setter Property='Background' Value='{DynamicResource brush}'/>
  206. </Style>
  207. </Window.Styles>
  208. <Button Name='button'/>
  209. </Window>";
  210. var loader = new AvaloniaXamlLoader();
  211. var window = (Window)loader.Load(xaml);
  212. var button = window.FindControl<Button>("button");
  213. var brush = (SolidColorBrush)button.Background;
  214. Assert.Equal(0xff506070, brush.Color.ToUint32());
  215. }
  216. }
  217. [Fact]
  218. public void DynamicResource_Can_Be_Assigned_To_Setter_In_Styles_File()
  219. {
  220. var styleXaml = @"
  221. <Styles xmlns='https://github.com/avaloniaui'
  222. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  223. <Styles.Resources>
  224. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  225. </Styles.Resources>
  226. <Style Selector='Border'>
  227. <Setter Property='Background' Value='{DynamicResource brush}'/>
  228. </Style>
  229. </Styles>";
  230. using (StyledWindow(assets: ("test:style.xaml", styleXaml)))
  231. {
  232. var xaml = @"
  233. <Window xmlns='https://github.com/avaloniaui'
  234. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  235. <Window.Styles>
  236. <StyleInclude Source='test:style.xaml'/>
  237. </Window.Styles>
  238. <Border Name='border'/>
  239. </Window>";
  240. var loader = new AvaloniaXamlLoader();
  241. var window = (Window)loader.Load(xaml);
  242. var border = window.FindControl<Border>("border");
  243. var brush = (SolidColorBrush)border.Background;
  244. Assert.Equal(0xff506070, brush.Color.ToUint32());
  245. }
  246. }
  247. [Fact]
  248. public void DynamicResource_Can_Be_Assigned_To_Property_In_ControlTemplate_In_Styles_File()
  249. {
  250. var styleXaml = @"
  251. <Styles xmlns='https://github.com/avaloniaui'
  252. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  253. <Styles.Resources>
  254. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  255. </Styles.Resources>
  256. <Style Selector='Button'>
  257. <Setter Property='Template'>
  258. <ControlTemplate>
  259. <Border Name='border' Background='{DynamicResource brush}'/>
  260. </ControlTemplate>
  261. </Setter>
  262. </Style>
  263. </Styles>";
  264. using (StyledWindow(assets: ("test:style.xaml", styleXaml)))
  265. {
  266. var xaml = @"
  267. <Window xmlns='https://github.com/avaloniaui'
  268. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  269. <Window.Styles>
  270. <StyleInclude Source='test:style.xaml'/>
  271. </Window.Styles>
  272. <Button Name='button'/>
  273. </Window>";
  274. var loader = new AvaloniaXamlLoader();
  275. var window = (Window)loader.Load(xaml);
  276. var button = window.FindControl<Button>("button");
  277. window.Show();
  278. var border = (Border)button.GetVisualChildren().Single();
  279. var brush = (SolidColorBrush)border.Background;
  280. Assert.Equal(0xff506070, brush.Color.ToUint32());
  281. }
  282. }
  283. [Fact]
  284. public void DynamicResource_Can_Be_Assigned_To_Resource_Property()
  285. {
  286. var xaml = @"
  287. <UserControl xmlns='https://github.com/avaloniaui'
  288. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  289. <UserControl.Resources>
  290. <Color x:Key='color'>#ff506070</Color>
  291. <SolidColorBrush x:Key='brush' Color='{DynamicResource color}'/>
  292. </UserControl.Resources>
  293. <Border Name='border' Background='{DynamicResource brush}'/>
  294. </UserControl>";
  295. var loader = new AvaloniaXamlLoader();
  296. var userControl = (UserControl)loader.Load(xaml);
  297. var border = userControl.FindControl<Border>("border");
  298. DelayedBinding.ApplyBindings(border);
  299. var brush = (SolidColorBrush)border.Background;
  300. Assert.Equal(0xff506070, brush.Color.ToUint32());
  301. }
  302. [Fact]
  303. public void DynamicResource_Can_Be_Assigned_To_ItemTemplate_Property()
  304. {
  305. var xaml = @"
  306. <UserControl xmlns='https://github.com/avaloniaui'
  307. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  308. <UserControl.Resources>
  309. <DataTemplate x:Key='PurpleData'>
  310. <TextBlock Text='{Binding Name}' Background='Purple'/>
  311. </DataTemplate>
  312. </UserControl.Resources>
  313. <ListBox Name='listBox' ItemTemplate='{DynamicResource PurpleData}'/>
  314. </UserControl>";
  315. var loader = new AvaloniaXamlLoader();
  316. var userControl = (UserControl)loader.Load(xaml);
  317. var listBox = userControl.FindControl<ListBox>("listBox");
  318. DelayedBinding.ApplyBindings(listBox);
  319. Assert.NotNull(listBox.ItemTemplate);
  320. }
  321. [Fact]
  322. public void DynamicResource_Tracks_Added_Resource()
  323. {
  324. var xaml = @"
  325. <UserControl xmlns='https://github.com/avaloniaui'
  326. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  327. <Border Name='border' Background='{DynamicResource brush}'/>
  328. </UserControl>";
  329. var loader = new AvaloniaXamlLoader();
  330. var userControl = (UserControl)loader.Load(xaml);
  331. var border = userControl.FindControl<Border>("border");
  332. DelayedBinding.ApplyBindings(border);
  333. Assert.Null(border.Background);
  334. userControl.Resources.Add("brush", new SolidColorBrush(0xff506070));
  335. var brush = (SolidColorBrush)border.Background;
  336. Assert.NotNull(brush);
  337. Assert.Equal(0xff506070, brush.Color.ToUint32());
  338. }
  339. [Fact]
  340. public void DynamicResource_Tracks_Added_Style_Resource()
  341. {
  342. var xaml = @"
  343. <UserControl xmlns='https://github.com/avaloniaui'
  344. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  345. <Border Name='border' Background='{DynamicResource brush}'/>
  346. </UserControl>";
  347. var loader = new AvaloniaXamlLoader();
  348. var userControl = (UserControl)loader.Load(xaml);
  349. var border = userControl.FindControl<Border>("border");
  350. DelayedBinding.ApplyBindings(border);
  351. Assert.Null(border.Background);
  352. userControl.Styles.Resources.Add("brush", new SolidColorBrush(0xff506070));
  353. var brush = (SolidColorBrush)border.Background;
  354. Assert.NotNull(brush);
  355. Assert.Equal(0xff506070, brush.Color.ToUint32());
  356. }
  357. [Fact]
  358. public void DynamicResource_Tracks_Added_Nested_Style_Resource()
  359. {
  360. var xaml = @"
  361. <UserControl xmlns='https://github.com/avaloniaui'
  362. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  363. <UserControl.Styles>
  364. <Style>
  365. </Style>
  366. </UserControl.Styles>
  367. <Border Name='border' Background='{DynamicResource brush}'/>
  368. </UserControl>";
  369. var loader = new AvaloniaXamlLoader();
  370. var userControl = (UserControl)loader.Load(xaml);
  371. var border = userControl.FindControl<Border>("border");
  372. DelayedBinding.ApplyBindings(border);
  373. Assert.Null(border.Background);
  374. ((Style)userControl.Styles[0]).Resources.Add("brush", new SolidColorBrush(0xff506070));
  375. var brush = (SolidColorBrush)border.Background;
  376. Assert.NotNull(brush);
  377. Assert.Equal(0xff506070, brush.Color.ToUint32());
  378. }
  379. [Fact]
  380. public void DynamicResource_Tracks_Added_MergedResource()
  381. {
  382. var xaml = @"
  383. <UserControl xmlns='https://github.com/avaloniaui'
  384. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  385. <UserControl.Resources>
  386. <ResourceDictionary>
  387. <ResourceDictionary.MergedDictionaries>
  388. <ResourceDictionary/>
  389. </ResourceDictionary.MergedDictionaries>
  390. </ResourceDictionary>
  391. </UserControl.Resources>
  392. <Border Name='border' Background='{DynamicResource brush}'/>
  393. </UserControl>";
  394. var loader = new AvaloniaXamlLoader();
  395. var userControl = (UserControl)loader.Load(xaml);
  396. var border = userControl.FindControl<Border>("border");
  397. DelayedBinding.ApplyBindings(border);
  398. Assert.Null(border.Background);
  399. ((IResourceDictionary)userControl.Resources.MergedDictionaries[0]).Add("brush", new SolidColorBrush(0xff506070));
  400. var brush = (SolidColorBrush)border.Background;
  401. Assert.NotNull(brush);
  402. Assert.Equal(0xff506070, brush.Color.ToUint32());
  403. }
  404. [Fact]
  405. public void DynamicResource_Tracks_Added_MergedResource_Dictionary()
  406. {
  407. var xaml = @"
  408. <UserControl xmlns='https://github.com/avaloniaui'
  409. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  410. <Border Name='border' Background='{DynamicResource brush}'/>
  411. </UserControl>";
  412. var loader = new AvaloniaXamlLoader();
  413. var userControl = (UserControl)loader.Load(xaml);
  414. var border = userControl.FindControl<Border>("border");
  415. DelayedBinding.ApplyBindings(border);
  416. Assert.Null(border.Background);
  417. var dictionary = new ResourceDictionary
  418. {
  419. { "brush", new SolidColorBrush(0xff506070) },
  420. };
  421. userControl.Resources.MergedDictionaries.Add(dictionary);
  422. var brush = (SolidColorBrush)border.Background;
  423. Assert.NotNull(brush);
  424. Assert.Equal(0xff506070, brush.Color.ToUint32());
  425. }
  426. [Fact]
  427. public void DynamicResource_Tracks_Added_Style_MergedResource_Dictionary()
  428. {
  429. var xaml = @"
  430. <UserControl xmlns='https://github.com/avaloniaui'
  431. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  432. <UserControl.Styles>
  433. <Style>
  434. </Style>
  435. </UserControl.Styles>
  436. <Border Name='border' Background='{DynamicResource brush}'/>
  437. </UserControl>";
  438. var loader = new AvaloniaXamlLoader();
  439. var userControl = (UserControl)loader.Load(xaml);
  440. var border = userControl.FindControl<Border>("border");
  441. DelayedBinding.ApplyBindings(border);
  442. Assert.Null(border.Background);
  443. var dictionary = new ResourceDictionary
  444. {
  445. { "brush", new SolidColorBrush(0xff506070) },
  446. };
  447. ((Style)userControl.Styles[0]).Resources.MergedDictionaries.Add(dictionary);
  448. var brush = (SolidColorBrush)border.Background;
  449. Assert.NotNull(brush);
  450. Assert.Equal(0xff506070, brush.Color.ToUint32());
  451. }
  452. [Fact]
  453. public void DynamicResource_Can_Be_Found_Across_Xaml_Style_Files()
  454. {
  455. var style1Xaml = @"
  456. <Style xmlns='https://github.com/avaloniaui'
  457. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  458. <Style.Resources>
  459. <Color x:Key='Red'>Red</Color>
  460. </Style.Resources>
  461. </Style>";
  462. var style2Xaml = @"
  463. <Style xmlns='https://github.com/avaloniaui'
  464. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  465. <Style.Resources>
  466. <SolidColorBrush x:Key='RedBrush' Color='{DynamicResource Red}'/>
  467. </Style.Resources>
  468. </Style>";
  469. using (StyledWindow(
  470. ("test:style1.xaml", style1Xaml),
  471. ("test:style2.xaml", style2Xaml)))
  472. {
  473. var xaml = @"
  474. <Window xmlns='https://github.com/avaloniaui'
  475. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  476. <Window.Styles>
  477. <StyleInclude Source='test:style1.xaml'/>
  478. <StyleInclude Source='test:style2.xaml'/>
  479. </Window.Styles>
  480. <Border Name='border' Background='{DynamicResource RedBrush}'/>
  481. </Window>";
  482. var loader = new AvaloniaXamlLoader();
  483. var window = (Window)loader.Load(xaml);
  484. var border = window.FindControl<Border>("border");
  485. var borderBrush = (ISolidColorBrush)border.Background;
  486. Assert.NotNull(borderBrush);
  487. Assert.Equal(0xffff0000, borderBrush.Color.ToUint32());
  488. }
  489. }
  490. [Fact]
  491. public void DynamicResource_Can_Be_Found_In_Nested_Style_File()
  492. {
  493. var style1Xaml = @"
  494. <Styles xmlns='https://github.com/avaloniaui'
  495. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  496. <StyleInclude Source='test:style2.xaml'/>
  497. </Styles>";
  498. var style2Xaml = @"
  499. <Style xmlns='https://github.com/avaloniaui'
  500. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  501. <Style.Resources>
  502. <Color x:Key='Red'>Red</Color>
  503. <SolidColorBrush x:Key='RedBrush' Color='{DynamicResource Red}'/>
  504. </Style.Resources>
  505. </Style>";
  506. using (StyledWindow(
  507. ("test:style1.xaml", style1Xaml),
  508. ("test:style2.xaml", style2Xaml)))
  509. {
  510. var xaml = @"
  511. <Window xmlns='https://github.com/avaloniaui'
  512. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  513. <Window.Styles>
  514. <StyleInclude Source='test:style1.xaml'/>
  515. </Window.Styles>
  516. <Border Name='border' Background='{DynamicResource RedBrush}'/>
  517. </Window>";
  518. var loader = new AvaloniaXamlLoader();
  519. var window = (Window)loader.Load(xaml);
  520. var border = window.FindControl<Border>("border");
  521. var borderBrush = (ISolidColorBrush)border.Background;
  522. Assert.NotNull(borderBrush);
  523. Assert.Equal(0xffff0000, borderBrush.Color.ToUint32());
  524. }
  525. }
  526. [Fact]
  527. public void Control_Property_Is_Updated_When_Parent_Is_Changed()
  528. {
  529. var xaml = @"
  530. <UserControl xmlns='https://github.com/avaloniaui'
  531. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  532. <UserControl.Resources>
  533. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  534. </UserControl.Resources>
  535. <Border Name='border' Background='{DynamicResource brush}'/>
  536. </UserControl>";
  537. var loader = new AvaloniaXamlLoader();
  538. var userControl = (UserControl)loader.Load(xaml);
  539. var border = userControl.FindControl<Border>("border");
  540. DelayedBinding.ApplyBindings(border);
  541. var brush = (SolidColorBrush)border.Background;
  542. Assert.Equal(0xff506070, brush.Color.ToUint32());
  543. userControl.Content = null;
  544. Assert.Null(border.Background);
  545. userControl.Content = border;
  546. brush = (SolidColorBrush)border.Background;
  547. Assert.Equal(0xff506070, brush.Color.ToUint32());
  548. }
  549. [Fact]
  550. public void Resource_With_DynamicResource_Is_Updated_When_Added_To_Parent()
  551. {
  552. var xaml = @"
  553. <UserControl xmlns='https://github.com/avaloniaui'
  554. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  555. <UserControl.Resources>
  556. <SolidColorBrush x:Key='brush' Color='{DynamicResource color}'/>
  557. </UserControl.Resources>
  558. <Border Name='border' Background='{DynamicResource brush}'/>
  559. </UserControl>";
  560. var loader = new AvaloniaXamlLoader();
  561. var userControl = (UserControl)loader.Load(xaml);
  562. var border = userControl.FindControl<Border>("border");
  563. DelayedBinding.ApplyBindings(border);
  564. var brush = (SolidColorBrush)border.Background;
  565. Assert.Equal(0u, brush.Color.ToUint32());
  566. brush.GetObservable(SolidColorBrush.ColorProperty).Subscribe(_ => { });
  567. using (UnitTestApplication.Start(TestServices.StyledWindow))
  568. {
  569. var window = new Window
  570. {
  571. Resources =
  572. {
  573. { "color", Colors.Red }
  574. },
  575. Content = userControl,
  576. };
  577. window.Show();
  578. Assert.Equal(Colors.Red, brush.Color);
  579. }
  580. }
  581. [Fact]
  582. public void MergedDictionary_Resource_With_DynamicResource_Is_Updated_When_Added_To_Parent()
  583. {
  584. var xaml = @"
  585. <UserControl xmlns='https://github.com/avaloniaui'
  586. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  587. <UserControl.Resources>
  588. <ResourceDictionary>
  589. <ResourceDictionary.MergedDictionaries>
  590. <ResourceDictionary>
  591. <SolidColorBrush x:Key='brush' Color='{DynamicResource color}'/>
  592. </ResourceDictionary>
  593. </ResourceDictionary.MergedDictionaries>
  594. </ResourceDictionary>
  595. </UserControl.Resources>
  596. <Border Name='border' Background='{DynamicResource brush}'/>
  597. </UserControl>";
  598. var loader = new AvaloniaXamlLoader();
  599. var userControl = (UserControl)loader.Load(xaml);
  600. var border = userControl.FindControl<Border>("border");
  601. DelayedBinding.ApplyBindings(border);
  602. var brush = (SolidColorBrush)border.Background;
  603. Assert.Equal(0u, brush.Color.ToUint32());
  604. brush.GetObservable(SolidColorBrush.ColorProperty).Subscribe(_ => { });
  605. using (UnitTestApplication.Start(TestServices.StyledWindow))
  606. {
  607. var window = new Window
  608. {
  609. Resources =
  610. {
  611. { "color", Colors.Red }
  612. },
  613. Content = userControl,
  614. };
  615. window.Show();
  616. Assert.Equal(Colors.Red, brush.Color);
  617. }
  618. }
  619. [Fact]
  620. public void Style_Resource_With_DynamicResource_Is_Updated_When_Added_To_Parent()
  621. {
  622. var xaml = @"
  623. <UserControl xmlns='https://github.com/avaloniaui'
  624. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  625. <UserControl.Styles>
  626. <Style>
  627. <Style.Resources>
  628. <SolidColorBrush x:Key='brush' Color='{DynamicResource color}'/>
  629. </Style.Resources>
  630. </Style>
  631. </UserControl.Styles>
  632. <Border Name='border' Background='{DynamicResource brush}'/>
  633. </UserControl>";
  634. var loader = new AvaloniaXamlLoader();
  635. var userControl = (UserControl)loader.Load(xaml);
  636. var border = userControl.FindControl<Border>("border");
  637. DelayedBinding.ApplyBindings(border);
  638. var brush = (SolidColorBrush)border.Background;
  639. Assert.Equal(0u, brush.Color.ToUint32());
  640. using (UnitTestApplication.Start(TestServices.StyledWindow))
  641. {
  642. var window = new Window
  643. {
  644. Resources =
  645. {
  646. { "color", Colors.Red }
  647. },
  648. Content = userControl,
  649. };
  650. window.Show();
  651. Assert.Equal(Colors.Red, brush.Color);
  652. }
  653. }
  654. private IDisposable StyledWindow(params (string, string)[] assets)
  655. {
  656. var services = TestServices.StyledWindow.With(
  657. assetLoader: new MockAssetLoader(assets),
  658. theme: () => new Styles
  659. {
  660. WindowStyle(),
  661. });
  662. return UnitTestApplication.Start(services);
  663. }
  664. private Style WindowStyle()
  665. {
  666. return new Style(x => x.OfType<Window>())
  667. {
  668. Setters =
  669. {
  670. new Setter(
  671. Window.TemplateProperty,
  672. new FuncControlTemplate<Window>((x, scope) =>
  673. new ContentPresenter
  674. {
  675. Name = "PART_ContentPresenter",
  676. [!ContentPresenter.ContentProperty] = x[!Window.ContentProperty],
  677. }.RegisterInNameScope(scope)))
  678. }
  679. };
  680. }
  681. }
  682. }