StaticResourceExtensionTests.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using System.Linq;
  5. using Avalonia.Controls;
  6. using Avalonia.Controls.Presenters;
  7. using Avalonia.Controls.Templates;
  8. using Avalonia.Media;
  9. using Avalonia.Styling;
  10. using Avalonia.UnitTests;
  11. using Avalonia.VisualTree;
  12. using Xunit;
  13. namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
  14. {
  15. public class StaticResourceExtensionTests
  16. {
  17. [Fact]
  18. public void StaticResource_Can_Be_Assigned_To_Property()
  19. {
  20. var xaml = @"
  21. <UserControl xmlns='https://github.com/avaloniaui'
  22. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  23. <UserControl.Resources>
  24. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  25. </UserControl.Resources>
  26. <Border Name='border' Background='{StaticResource brush}'/>
  27. </UserControl>";
  28. var loader = new AvaloniaXamlLoader();
  29. var userControl = (UserControl)loader.Load(xaml);
  30. var border = userControl.FindControl<Border>("border");
  31. var brush = (SolidColorBrush)border.Background;
  32. Assert.Equal(0xff506070, brush.Color.ToUint32());
  33. }
  34. [Fact]
  35. public void StaticResource_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='{StaticResource col}'/>
  44. </UserControl>";
  45. var loader = new AvaloniaXamlLoader();
  46. var userControl = (UserControl)loader.Load(xaml);
  47. var border = userControl.FindControl<Border>("border");
  48. Assert.Equal(5, Grid.GetColumn(border));
  49. }
  50. [Fact]
  51. public void StaticResource_From_Style_Can_Be_Assigned_To_Property()
  52. {
  53. var xaml = @"
  54. <UserControl xmlns='https://github.com/avaloniaui'
  55. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  56. <UserControl.Styles>
  57. <Style>
  58. <Style.Resources>
  59. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  60. </Style.Resources>
  61. </Style>
  62. </UserControl.Styles>
  63. <Border Name='border' Background='{StaticResource brush}'/>
  64. </UserControl>";
  65. var loader = new AvaloniaXamlLoader();
  66. var userControl = (UserControl)loader.Load(xaml);
  67. var border = userControl.FindControl<Border>("border");
  68. var brush = (SolidColorBrush)border.Background;
  69. Assert.Equal(0xff506070, brush.Color.ToUint32());
  70. }
  71. [Fact]
  72. public void StaticResource_From_Application_Can_Be_Assigned_To_Property_In_Window()
  73. {
  74. using (StyledWindow())
  75. {
  76. Application.Current.Resources.Add("brush", new SolidColorBrush(0xff506070));
  77. var xaml = @"
  78. <Window xmlns='https://github.com/avaloniaui'
  79. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  80. <Border Name='border' Background='{StaticResource brush}'/>
  81. </Window>";
  82. var loader = new AvaloniaXamlLoader();
  83. var window = (Window)loader.Load(xaml);
  84. var border = window.FindControl<Border>("border");
  85. var brush = (SolidColorBrush)border.Background;
  86. Assert.Equal(0xff506070, brush.Color.ToUint32());
  87. }
  88. }
  89. [Fact]
  90. public void StaticResource_From_MergedDictionary_Can_Be_Assigned_To_Property()
  91. {
  92. var xaml = @"
  93. <UserControl xmlns='https://github.com/avaloniaui'
  94. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  95. <UserControl.Resources>
  96. <ResourceDictionary>
  97. <ResourceDictionary.MergedDictionaries>
  98. <ResourceDictionary>
  99. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  100. </ResourceDictionary>
  101. </ResourceDictionary.MergedDictionaries>
  102. </ResourceDictionary>
  103. </UserControl.Resources>
  104. <Border Name='border' Background='{StaticResource brush}'/>
  105. </UserControl>";
  106. var loader = new AvaloniaXamlLoader();
  107. var userControl = (UserControl)loader.Load(xaml);
  108. var border = userControl.FindControl<Border>("border");
  109. var brush = (SolidColorBrush)border.Background;
  110. Assert.Equal(0xff506070, brush.Color.ToUint32());
  111. }
  112. [Fact]
  113. public void StaticResource_From_MergedDictionary_In_Style_Can_Be_Assigned_To_Property()
  114. {
  115. var xaml = @"
  116. <UserControl xmlns='https://github.com/avaloniaui'
  117. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  118. <UserControl.Styles>
  119. <Style>
  120. <Style.Resources>
  121. <ResourceDictionary>
  122. <ResourceDictionary.MergedDictionaries>
  123. <ResourceDictionary>
  124. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  125. </ResourceDictionary>
  126. </ResourceDictionary.MergedDictionaries>
  127. </ResourceDictionary>
  128. </Style.Resources>
  129. </Style>
  130. </UserControl.Styles>
  131. <Border Name='border' Background='{StaticResource brush}'/>
  132. </UserControl>";
  133. var loader = new AvaloniaXamlLoader();
  134. var userControl = (UserControl)loader.Load(xaml);
  135. var border = userControl.FindControl<Border>("border");
  136. var brush = (SolidColorBrush)border.Background;
  137. Assert.Equal(0xff506070, brush.Color.ToUint32());
  138. }
  139. [Fact]
  140. public void StaticResource_From_Application_Can_Be_Assigned_To_Property_In_UserControl()
  141. {
  142. using (UnitTestApplication.Start(TestServices.StyledWindow))
  143. {
  144. Application.Current.Resources.Add("brush", new SolidColorBrush(0xff506070));
  145. var xaml = @"
  146. <UserControl xmlns='https://github.com/avaloniaui'
  147. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  148. <Border Name='border' Background='{StaticResource brush}'/>
  149. </UserControl>";
  150. var loader = new AvaloniaXamlLoader();
  151. var userControl = (UserControl)loader.Load(xaml);
  152. var border = userControl.FindControl<Border>("border");
  153. // We don't actually know where the global styles are until we attach the control
  154. // to a window, as Window has StylingParent set to Application.
  155. var window = new Window { Content = userControl };
  156. window.Show();
  157. var brush = (SolidColorBrush)border.Background;
  158. Assert.Equal(0xff506070, brush.Color.ToUint32());
  159. }
  160. }
  161. [Fact]
  162. public void StaticResource_Can_Be_Assigned_To_Setter()
  163. {
  164. using (StyledWindow())
  165. {
  166. var xaml = @"
  167. <Window xmlns='https://github.com/avaloniaui'
  168. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  169. <Window.Resources>
  170. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  171. </Window.Resources>
  172. <Window.Styles>
  173. <Style Selector='Button'>
  174. <Setter Property='Background' Value='{StaticResource brush}'/>
  175. </Style>
  176. </Window.Styles>
  177. <Button Name='button'/>
  178. </Window>";
  179. var loader = new AvaloniaXamlLoader();
  180. var window = (Window)loader.Load(xaml);
  181. var button = window.FindControl<Button>("button");
  182. var brush = (SolidColorBrush)button.Background;
  183. Assert.Equal(0xff506070, brush.Color.ToUint32());
  184. }
  185. }
  186. [Fact]
  187. public void StaticResource_From_Style_Can_Be_Assigned_To_Setter()
  188. {
  189. using (StyledWindow())
  190. {
  191. var xaml = @"
  192. <Window xmlns='https://github.com/avaloniaui'
  193. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  194. <Window.Styles>
  195. <Style>
  196. <Style.Resources>
  197. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  198. </Style.Resources>
  199. </Style>
  200. <Style Selector='Button'>
  201. <Setter Property='Background' Value='{StaticResource brush}'/>
  202. </Style>
  203. </Window.Styles>
  204. <Button Name='button'/>
  205. </Window>";
  206. var loader = new AvaloniaXamlLoader();
  207. var window = (Window)loader.Load(xaml);
  208. var button = window.FindControl<Button>("button");
  209. var brush = (SolidColorBrush)button.Background;
  210. Assert.Equal(0xff506070, brush.Color.ToUint32());
  211. }
  212. }
  213. [Fact]
  214. public void StaticResource_Can_Be_Assigned_To_Setter_In_Styles_File()
  215. {
  216. var styleXaml = @"
  217. <Styles xmlns='https://github.com/avaloniaui'
  218. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  219. <Styles.Resources>
  220. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  221. </Styles.Resources>
  222. <Style Selector='Border'>
  223. <Setter Property='Background' Value='{StaticResource brush}'/>
  224. </Style>
  225. </Styles>";
  226. using (StyledWindow(assets: ("test:style.xaml", styleXaml)))
  227. {
  228. var xaml = @"
  229. <Window xmlns='https://github.com/avaloniaui'
  230. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  231. <Window.Styles>
  232. <StyleInclude Source='test:style.xaml'/>
  233. </Window.Styles>
  234. <Border Name='border'/>
  235. </Window>";
  236. var loader = new AvaloniaXamlLoader();
  237. var window = (Window)loader.Load(xaml);
  238. var border = window.FindControl<Border>("border");
  239. var brush = (SolidColorBrush)border.Background;
  240. Assert.Equal(0xff506070, brush.Color.ToUint32());
  241. }
  242. }
  243. [Fact]
  244. public void StaticResource_Can_Be_Assigned_To_Resource_Property()
  245. {
  246. var xaml = @"
  247. <UserControl xmlns='https://github.com/avaloniaui'
  248. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  249. <UserControl.Resources>
  250. <Color x:Key='color'>#ff506070</Color>
  251. <SolidColorBrush x:Key='brush' Color='{StaticResource color}'/>
  252. </UserControl.Resources>
  253. <Border Name='border' Background='{StaticResource brush}'/>
  254. </UserControl>";
  255. var loader = new AvaloniaXamlLoader();
  256. var userControl = (UserControl)loader.Load(xaml);
  257. var border = userControl.FindControl<Border>("border");
  258. var brush = (SolidColorBrush)border.Background;
  259. Assert.Equal(0xff506070, brush.Color.ToUint32());
  260. }
  261. [Fact]
  262. public void StaticResource_Can_Be_Assigned_To_Resource_Property_In_Styles_File()
  263. {
  264. var xaml = @"
  265. <Styles xmlns='https://github.com/avaloniaui'
  266. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  267. <Styles.Resources>
  268. <Color x:Key='color'>#ff506070</Color>
  269. <SolidColorBrush x:Key='brush' Color='{StaticResource color}'/>
  270. </Styles.Resources>
  271. </Styles>";
  272. var loader = new AvaloniaXamlLoader();
  273. var styles = (Styles)loader.Load(xaml);
  274. var brush = (SolidColorBrush)styles.Resources["brush"];
  275. Assert.Equal(0xff506070, brush.Color.ToUint32());
  276. }
  277. [Fact(Skip = "Not yet supported by Portable.Xaml")]
  278. public void StaticResource_Can_Be_Assigned_To_Property_In_ControlTemplate_In_Styles_File()
  279. {
  280. var styleXaml = @"
  281. <Styles xmlns='https://github.com/avaloniaui'
  282. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  283. <Styles.Resources>
  284. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  285. </Styles.Resources>
  286. <Style Selector='Button'>
  287. <Setter Property='Template'>
  288. <ControlTemplate>
  289. <Border Name='border' Background='{StaticResource brush}'/>
  290. </ControlTemplate>
  291. </Setter>
  292. </Style>
  293. </Styles>";
  294. using (StyledWindow(assets: ("test:style.xaml", styleXaml)))
  295. {
  296. var xaml = @"
  297. <Window xmlns='https://github.com/avaloniaui'
  298. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  299. <Window.Styles>
  300. <StyleInclude Source='test:style.xaml'/>
  301. </Window.Styles>
  302. <Button Name='button'/>
  303. </Window>";
  304. var loader = new AvaloniaXamlLoader();
  305. var window = (Window)loader.Load(xaml);
  306. var button = window.FindControl<Button>("button");
  307. window.Show();
  308. var border = (Border)button.GetVisualChildren().Single();
  309. var brush = (SolidColorBrush)border.Background;
  310. // To make this work we somehow need to be able to get hold of the parent ambient
  311. // context from Portable.Xaml. See TODO in StaticResourceExtension.
  312. Assert.Equal(0xff506070, brush.Color.ToUint32());
  313. }
  314. }
  315. [Fact]
  316. public void StaticResource_Can_Be_Assigned_To_ItemTemplate_Property()
  317. {
  318. var xaml = @"
  319. <UserControl xmlns='https://github.com/avaloniaui'
  320. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  321. <UserControl.Resources>
  322. <DataTemplate x:Key='PurpleData'>
  323. <TextBlock Text='{Binding Name}' Background='Purple'/>
  324. </DataTemplate>
  325. </UserControl.Resources>
  326. <ListBox Name='listBox' ItemTemplate='{StaticResource PurpleData}'/>
  327. </UserControl>";
  328. var loader = new AvaloniaXamlLoader();
  329. var userControl = (UserControl)loader.Load(xaml);
  330. var listBox = userControl.FindControl<ListBox>("listBox");
  331. Assert.NotNull(listBox.ItemTemplate);
  332. }
  333. [Fact]
  334. public void StaticResource_Can_Be_Assigned_To_Converter()
  335. {
  336. using (StyledWindow())
  337. {
  338. var xaml = @"
  339. <Window xmlns='https://github.com/avaloniaui'
  340. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  341. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  342. <Window.Resources>
  343. <local:TestValueConverter x:Key='converter' Append='bar'/>
  344. </Window.Resources>
  345. <TextBlock Name='textBlock' Text='{Binding Converter={StaticResource converter}}'/>
  346. </Window>";
  347. var loader = new AvaloniaXamlLoader();
  348. var window = (Window)loader.Load(xaml);
  349. var textBlock = window.FindControl<TextBlock>("textBlock");
  350. window.DataContext = "foo";
  351. window.ApplyTemplate();
  352. Assert.Equal("foobar", textBlock.Text);
  353. }
  354. }
  355. [Fact]
  356. public void Control_Property_Is_Not_Updated_When_Parent_Is_Changed()
  357. {
  358. var xaml = @"
  359. <UserControl xmlns='https://github.com/avaloniaui'
  360. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  361. <UserControl.Resources>
  362. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  363. </UserControl.Resources>
  364. <Border Name='border' Background='{StaticResource brush}'/>
  365. </UserControl>";
  366. var loader = new AvaloniaXamlLoader();
  367. var userControl = (UserControl)loader.Load(xaml);
  368. var border = userControl.FindControl<Border>("border");
  369. var brush = (SolidColorBrush)border.Background;
  370. Assert.Equal(0xff506070, brush.Color.ToUint32());
  371. userControl.Content = null;
  372. brush = (SolidColorBrush)border.Background;
  373. Assert.Equal(0xff506070, brush.Color.ToUint32());
  374. }
  375. private IDisposable StyledWindow(params (string, string)[] assets)
  376. {
  377. var services = TestServices.StyledWindow.With(
  378. assetLoader: new MockAssetLoader(assets),
  379. theme: () => new Styles
  380. {
  381. WindowStyle(),
  382. });
  383. return UnitTestApplication.Start(services);
  384. }
  385. private Style WindowStyle()
  386. {
  387. return new Style(x => x.OfType<Window>())
  388. {
  389. Setters =
  390. {
  391. new Setter(
  392. Window.TemplateProperty,
  393. new FuncControlTemplate<Window>(x =>
  394. new ContentPresenter
  395. {
  396. Name = "PART_ContentPresenter",
  397. [!ContentPresenter.ContentProperty] = x[!Window.ContentProperty],
  398. }))
  399. }
  400. };
  401. }
  402. }
  403. }