StaticResourceExtensionTests.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  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_Application_Can_Be_Assigned_To_Property_In_UserControl()
  91. {
  92. using (UnitTestApplication.Start(TestServices.StyledWindow))
  93. {
  94. Application.Current.Resources.Add("brush", new SolidColorBrush(0xff506070));
  95. var xaml = @"
  96. <UserControl xmlns='https://github.com/avaloniaui'
  97. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  98. <Border Name='border' Background='{StaticResource brush}'/>
  99. </UserControl>";
  100. var loader = new AvaloniaXamlLoader();
  101. var userControl = (UserControl)loader.Load(xaml);
  102. var border = userControl.FindControl<Border>("border");
  103. // We don't actually know where the global styles are until we attach the control
  104. // to a window, as Window has StylingParent set to Application.
  105. var window = new Window { Content = userControl };
  106. window.Show();
  107. var brush = (SolidColorBrush)border.Background;
  108. Assert.Equal(0xff506070, brush.Color.ToUint32());
  109. }
  110. }
  111. [Fact]
  112. public void StaticResource_Can_Be_Assigned_To_Setter()
  113. {
  114. using (StyledWindow())
  115. {
  116. var xaml = @"
  117. <Window xmlns='https://github.com/avaloniaui'
  118. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  119. <Window.Resources>
  120. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  121. </Window.Resources>
  122. <Window.Styles>
  123. <Style Selector='Button'>
  124. <Setter Property='Background' Value='{StaticResource brush}'/>
  125. </Style>
  126. </Window.Styles>
  127. <Button Name='button'/>
  128. </Window>";
  129. var loader = new AvaloniaXamlLoader();
  130. var window = (Window)loader.Load(xaml);
  131. var button = window.FindControl<Button>("button");
  132. var brush = (SolidColorBrush)button.Background;
  133. Assert.Equal(0xff506070, brush.Color.ToUint32());
  134. }
  135. }
  136. [Fact]
  137. public void StaticResource_From_Style_Can_Be_Assigned_To_Setter()
  138. {
  139. using (StyledWindow())
  140. {
  141. var xaml = @"
  142. <Window xmlns='https://github.com/avaloniaui'
  143. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  144. <Window.Styles>
  145. <Style>
  146. <Style.Resources>
  147. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  148. </Style.Resources>
  149. </Style>
  150. <Style Selector='Button'>
  151. <Setter Property='Background' Value='{StaticResource brush}'/>
  152. </Style>
  153. </Window.Styles>
  154. <Button Name='button'/>
  155. </Window>";
  156. var loader = new AvaloniaXamlLoader();
  157. var window = (Window)loader.Load(xaml);
  158. var button = window.FindControl<Button>("button");
  159. var brush = (SolidColorBrush)button.Background;
  160. Assert.Equal(0xff506070, brush.Color.ToUint32());
  161. }
  162. }
  163. [Fact]
  164. public void StaticResource_Can_Be_Assigned_To_Setter_In_Styles_File()
  165. {
  166. var styleXaml = @"
  167. <Styles xmlns='https://github.com/avaloniaui'
  168. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  169. <Styles.Resources>
  170. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  171. </Styles.Resources>
  172. <Style Selector='Border'>
  173. <Setter Property='Background' Value='{StaticResource brush}'/>
  174. </Style>
  175. </Styles>";
  176. using (StyledWindow(assets: ("test:style.xaml", styleXaml)))
  177. {
  178. var xaml = @"
  179. <Window xmlns='https://github.com/avaloniaui'
  180. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  181. <Window.Styles>
  182. <StyleInclude Source='test:style.xaml'/>
  183. </Window.Styles>
  184. <Border Name='border'/>
  185. </Window>";
  186. var loader = new AvaloniaXamlLoader();
  187. var window = (Window)loader.Load(xaml);
  188. var border = window.FindControl<Border>("border");
  189. var brush = (SolidColorBrush)border.Background;
  190. Assert.Equal(0xff506070, brush.Color.ToUint32());
  191. }
  192. }
  193. [Fact]
  194. public void StaticResource_Can_Be_Assigned_To_Resource_Property()
  195. {
  196. var xaml = @"
  197. <UserControl xmlns='https://github.com/avaloniaui'
  198. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  199. <UserControl.Resources>
  200. <Color x:Key='color'>#ff506070</Color>
  201. <SolidColorBrush x:Key='brush' Color='{StaticResource color}'/>
  202. </UserControl.Resources>
  203. <Border Name='border' Background='{StaticResource brush}'/>
  204. </UserControl>";
  205. var loader = new AvaloniaXamlLoader();
  206. var userControl = (UserControl)loader.Load(xaml);
  207. var border = userControl.FindControl<Border>("border");
  208. var brush = (SolidColorBrush)border.Background;
  209. Assert.Equal(0xff506070, brush.Color.ToUint32());
  210. }
  211. [Fact]
  212. public void StaticResource_Can_Be_Assigned_To_Resource_Property_In_Styles_File()
  213. {
  214. var xaml = @"
  215. <Styles xmlns='https://github.com/avaloniaui'
  216. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  217. <Styles.Resources>
  218. <Color x:Key='color'>#ff506070</Color>
  219. <SolidColorBrush x:Key='brush' Color='{StaticResource color}'/>
  220. </Styles.Resources>
  221. </Styles>";
  222. var loader = new AvaloniaXamlLoader();
  223. var styles = (Styles)loader.Load(xaml);
  224. var brush = (SolidColorBrush)styles.Resources["brush"];
  225. Assert.Equal(0xff506070, brush.Color.ToUint32());
  226. }
  227. [Fact(Skip = "Not yet supported by Portable.Xaml")]
  228. public void StaticResource_Can_Be_Assigned_To_Property_In_ControlTemplate_In_Styles_File()
  229. {
  230. var styleXaml = @"
  231. <Styles xmlns='https://github.com/avaloniaui'
  232. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  233. <Styles.Resources>
  234. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  235. </Styles.Resources>
  236. <Style Selector='Button'>
  237. <Setter Property='Template'>
  238. <ControlTemplate>
  239. <Border Name='border' Background='{StaticResource brush}'/>
  240. </ControlTemplate>
  241. </Setter>
  242. </Style>
  243. </Styles>";
  244. using (StyledWindow(assets: ("test:style.xaml", styleXaml)))
  245. {
  246. var xaml = @"
  247. <Window xmlns='https://github.com/avaloniaui'
  248. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  249. <Window.Styles>
  250. <StyleInclude Source='test:style.xaml'/>
  251. </Window.Styles>
  252. <Button Name='button'/>
  253. </Window>";
  254. var loader = new AvaloniaXamlLoader();
  255. var window = (Window)loader.Load(xaml);
  256. var button = window.FindControl<Button>("button");
  257. window.Show();
  258. var border = (Border)button.GetVisualChildren().Single();
  259. var brush = (SolidColorBrush)border.Background;
  260. // To make this work we somehow need to be able to get hold of the parent ambient
  261. // context from Portable.Xaml. See TODO in StaticResourceExtension.
  262. Assert.Equal(0xff506070, brush.Color.ToUint32());
  263. }
  264. }
  265. [Fact]
  266. public void StaticResource_Can_Be_Assigned_To_ItemTemplate_Property()
  267. {
  268. var xaml = @"
  269. <UserControl xmlns='https://github.com/avaloniaui'
  270. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  271. <UserControl.Resources>
  272. <DataTemplate x:Key='PurpleData'>
  273. <TextBlock Text='{Binding Name}' Background='Purple'/>
  274. </DataTemplate>
  275. </UserControl.Resources>
  276. <ListBox Name='listBox' ItemTemplate='{StaticResource PurpleData}'/>
  277. </UserControl>";
  278. var loader = new AvaloniaXamlLoader();
  279. var userControl = (UserControl)loader.Load(xaml);
  280. var listBox = userControl.FindControl<ListBox>("listBox");
  281. Assert.NotNull(listBox.ItemTemplate);
  282. }
  283. [Fact]
  284. public void StaticResource_Can_Be_Assigned_To_Converter()
  285. {
  286. using (StyledWindow())
  287. {
  288. var xaml = @"
  289. <Window xmlns='https://github.com/avaloniaui'
  290. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
  291. xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'>
  292. <Window.Resources>
  293. <local:TestValueConverter x:Key='converter' Append='bar'/>
  294. </Window.Resources>
  295. <TextBlock Name='textBlock' Text='{Binding Converter={StaticResource converter}}'/>
  296. </Window>";
  297. var loader = new AvaloniaXamlLoader();
  298. var window = (Window)loader.Load(xaml);
  299. var textBlock = window.FindControl<TextBlock>("textBlock");
  300. window.DataContext = "foo";
  301. window.ApplyTemplate();
  302. Assert.Equal("foobar", textBlock.Text);
  303. }
  304. }
  305. [Fact]
  306. public void Control_Property_Is_Not_Updated_When_Parent_Is_Changed()
  307. {
  308. var xaml = @"
  309. <UserControl xmlns='https://github.com/avaloniaui'
  310. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  311. <UserControl.Resources>
  312. <SolidColorBrush x:Key='brush'>#ff506070</SolidColorBrush>
  313. </UserControl.Resources>
  314. <Border Name='border' Background='{StaticResource brush}'/>
  315. </UserControl>";
  316. var loader = new AvaloniaXamlLoader();
  317. var userControl = (UserControl)loader.Load(xaml);
  318. var border = userControl.FindControl<Border>("border");
  319. var brush = (SolidColorBrush)border.Background;
  320. Assert.Equal(0xff506070, brush.Color.ToUint32());
  321. userControl.Content = null;
  322. brush = (SolidColorBrush)border.Background;
  323. Assert.Equal(0xff506070, brush.Color.ToUint32());
  324. }
  325. private IDisposable StyledWindow(params (string, string)[] assets)
  326. {
  327. var services = TestServices.StyledWindow.With(
  328. assetLoader: new MockAssetLoader(assets),
  329. theme: () => new Styles
  330. {
  331. WindowStyle(),
  332. });
  333. return UnitTestApplication.Start(services);
  334. }
  335. private Style WindowStyle()
  336. {
  337. return new Style(x => x.OfType<Window>())
  338. {
  339. Setters =
  340. {
  341. new Setter(
  342. Window.TemplateProperty,
  343. new FuncControlTemplate<Window>(x =>
  344. new ContentPresenter
  345. {
  346. Name = "PART_ContentPresenter",
  347. [!ContentPresenter.ContentProperty] = x[!Window.ContentProperty],
  348. }))
  349. }
  350. };
  351. }
  352. }
  353. }