ResourceDictionaryTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. using System;
  2. using Avalonia.Controls;
  3. using Avalonia.Controls.Presenters;
  4. using Avalonia.Controls.Templates;
  5. using Avalonia.Media;
  6. using Avalonia.Media.Immutable;
  7. using Avalonia.Styling;
  8. using Avalonia.UnitTests;
  9. using Xunit;
  10. namespace Avalonia.Markup.Xaml.UnitTests.Xaml
  11. {
  12. public class ResourceDictionaryTests : XamlTestBase
  13. {
  14. [Fact]
  15. public void StaticResource_Works_In_ResourceDictionary()
  16. {
  17. using (StyledWindow())
  18. {
  19. var xaml = @"
  20. <ResourceDictionary xmlns='https://github.com/avaloniaui'
  21. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  22. <Color x:Key='Red'>Red</Color>
  23. <SolidColorBrush x:Key='RedBrush' Color='{StaticResource Red}'/>
  24. </ResourceDictionary>";
  25. var resources = (ResourceDictionary)AvaloniaRuntimeXamlLoader.Load(xaml);
  26. var brush = (SolidColorBrush)resources["RedBrush"];
  27. Assert.Equal(Colors.Red, brush.Color);
  28. }
  29. }
  30. [Fact]
  31. public void DynamicResource_Finds_Resource_In_Parent_Dictionary()
  32. {
  33. var dictionaryXaml = @"
  34. <ResourceDictionary xmlns='https://github.com/avaloniaui'
  35. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  36. <SolidColorBrush x:Key='RedBrush' Color='{DynamicResource Red}'/>
  37. </ResourceDictionary>";
  38. using (StyledWindow(assets: ("test:dict.xaml", dictionaryXaml)))
  39. {
  40. var xaml = @"
  41. <Window xmlns='https://github.com/avaloniaui'
  42. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  43. <Window.Resources>
  44. <ResourceDictionary>
  45. <ResourceDictionary.MergedDictionaries>
  46. <ResourceInclude Source='test:dict.xaml'/>
  47. </ResourceDictionary.MergedDictionaries>
  48. </ResourceDictionary>
  49. <Color x:Key='Red'>Red</Color>
  50. </Window.Resources>
  51. <Button Name='button' Background='{DynamicResource RedBrush}'/>
  52. </Window>";
  53. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  54. var button = window.FindControl<Button>("button");
  55. var brush = Assert.IsType<SolidColorBrush>(button.Background);
  56. Assert.Equal(Colors.Red, brush.Color);
  57. window.Resources["Red"] = Colors.Green;
  58. Assert.Equal(Colors.Green, brush.Color);
  59. }
  60. }
  61. [Fact]
  62. public void Item_Is_Added_To_ResourceDictionary_As_Deferred()
  63. {
  64. using (StyledWindow())
  65. {
  66. var xaml = @"
  67. <ResourceDictionary xmlns='https://github.com/avaloniaui'
  68. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  69. <SolidColorBrush x:Key='Red' Color='Red' />
  70. </ResourceDictionary>";
  71. var resources = (ResourceDictionary)AvaloniaRuntimeXamlLoader.Load(xaml);
  72. Assert.True(resources.ContainsDeferredKey("Red"));
  73. }
  74. }
  75. [Fact]
  76. public void Item_Added_To_ResourceDictionary_Is_UnDeferred_On_Read()
  77. {
  78. using (StyledWindow())
  79. {
  80. var xaml = @"
  81. <ResourceDictionary xmlns='https://github.com/avaloniaui'
  82. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  83. <SolidColorBrush x:Key='Red' Color='Red' />
  84. </ResourceDictionary>";
  85. var resources = (ResourceDictionary)AvaloniaRuntimeXamlLoader.Load(xaml);
  86. Assert.True(resources.ContainsDeferredKey("Red"));
  87. Assert.IsType<SolidColorBrush>(resources["Red"]);
  88. Assert.False(resources.ContainsDeferredKey("Red"));
  89. }
  90. }
  91. [Fact]
  92. public void Item_Is_Added_To_Window_Resources_As_Deferred()
  93. {
  94. using (StyledWindow())
  95. {
  96. var xaml = @"
  97. <Window xmlns='https://github.com/avaloniaui'
  98. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  99. <Window.Resources>
  100. <SolidColorBrush x:Key='Red' Color='Red' />
  101. </Window.Resources>
  102. </Window>";
  103. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  104. var resources = (ResourceDictionary)window.Resources;
  105. Assert.True(resources.ContainsDeferredKey("Red"));
  106. }
  107. }
  108. [Fact]
  109. public void Item_Is_Added_To_Window_MergedDictionaries_As_Deferred()
  110. {
  111. using (StyledWindow())
  112. {
  113. var xaml = @"
  114. <Window xmlns='https://github.com/avaloniaui'
  115. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  116. <Window.Resources>
  117. <ResourceDictionary>
  118. <ResourceDictionary.MergedDictionaries>
  119. <ResourceDictionary>
  120. <SolidColorBrush x:Key='Red' Color='Red' />
  121. </ResourceDictionary>
  122. </ResourceDictionary.MergedDictionaries>
  123. </ResourceDictionary>
  124. </Window.Resources>
  125. </Window>";
  126. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  127. var resources = (ResourceDictionary)window.Resources.MergedDictionaries[0];
  128. Assert.True(resources.ContainsDeferredKey("Red"));
  129. }
  130. }
  131. [Fact]
  132. public void Item_Is_Added_To_Style_Resources_As_Deferred()
  133. {
  134. using (StyledWindow())
  135. {
  136. var xaml = @"
  137. <Style xmlns='https://github.com/avaloniaui'
  138. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  139. <Style.Resources>
  140. <SolidColorBrush x:Key='Red' Color='Red' />
  141. </Style.Resources>
  142. </Style>";
  143. var style = (Style)AvaloniaRuntimeXamlLoader.Load(xaml);
  144. var resources = (ResourceDictionary)style.Resources;
  145. Assert.True(resources.ContainsDeferredKey("Red"));
  146. }
  147. }
  148. [Fact]
  149. public void Item_Is_Added_To_Styles_Resources_As_Deferred()
  150. {
  151. using (StyledWindow())
  152. {
  153. var xaml = @"
  154. <Styles xmlns='https://github.com/avaloniaui'
  155. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  156. <Styles.Resources>
  157. <SolidColorBrush x:Key='Red' Color='Red' />
  158. </Styles.Resources>
  159. </Styles>";
  160. var style = (Styles)AvaloniaRuntimeXamlLoader.Load(xaml);
  161. var resources = (ResourceDictionary)style.Resources;
  162. Assert.True(resources.ContainsDeferredKey("Red"));
  163. }
  164. }
  165. [Fact]
  166. public void Item_Can_Be_StaticReferenced_As_Deferred()
  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='Red' Color='Red' />
  175. </Window.Resources>
  176. <Button>
  177. <Button.Resources>
  178. <StaticResource x:Key='Red2' ResourceKey='Red' />
  179. </Button.Resources>
  180. </Button>
  181. </Window>";
  182. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  183. var windowResources = (ResourceDictionary)window.Resources;
  184. var buttonResources = (ResourceDictionary)((Button)window.Content!).Resources;
  185. Assert.True(windowResources.ContainsDeferredKey("Red"));
  186. Assert.True(buttonResources.ContainsDeferredKey("Red2"));
  187. }
  188. }
  189. [Fact]
  190. public void Item_StaticReferenced_Is_UnDeferred_On_Read()
  191. {
  192. using (StyledWindow())
  193. {
  194. var xaml = @"
  195. <Window xmlns='https://github.com/avaloniaui'
  196. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  197. <Window.Resources>
  198. <SolidColorBrush x:Key='Red' Color='Red' />
  199. </Window.Resources>
  200. <Button>
  201. <Button.Resources>
  202. <StaticResource x:Key='Red2' ResourceKey='Red' />
  203. </Button.Resources>
  204. </Button>
  205. </Window>";
  206. var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
  207. var windowResources = (ResourceDictionary)window.Resources;
  208. var buttonResources = (ResourceDictionary)((Button)window.Content!).Resources;
  209. Assert.IsType<SolidColorBrush>(buttonResources["Red2"]);
  210. Assert.False(windowResources.ContainsDeferredKey("Red"));
  211. Assert.False(buttonResources.ContainsDeferredKey("Red2"));
  212. }
  213. }
  214. [Fact]
  215. public void Value_Type_With_Parse_Converter_Should_Not_Be_Deferred()
  216. {
  217. using (StyledWindow())
  218. {
  219. var xaml = @"
  220. <ResourceDictionary xmlns='https://github.com/avaloniaui'
  221. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  222. <Color x:Key='Red'>Red</Color>
  223. </ResourceDictionary>";
  224. var resources = (ResourceDictionary)AvaloniaRuntimeXamlLoader.Load(xaml);
  225. Assert.False(resources.ContainsDeferredKey("Red"));
  226. Assert.IsType<Color>(resources["Red"]);
  227. }
  228. }
  229. [Fact]
  230. public void Value_Type_With_Ctor_Converter_Should_Not_Be_Deferred()
  231. {
  232. using (StyledWindow())
  233. {
  234. var xaml = @"
  235. <ResourceDictionary xmlns='https://github.com/avaloniaui'
  236. xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
  237. <Thickness x:Key='Margin'>1 1 1 1</Thickness>
  238. </ResourceDictionary>";
  239. var resources = (ResourceDictionary)AvaloniaRuntimeXamlLoader.Load(xaml);
  240. Assert.False(resources.ContainsDeferredKey("Margin"));
  241. Assert.IsType<Thickness>(resources["Margin"]);
  242. }
  243. }
  244. private IDisposable StyledWindow(params (string, string)[] assets)
  245. {
  246. var services = TestServices.StyledWindow.With(
  247. assetLoader: new MockAssetLoader(assets),
  248. theme: () => new Styles
  249. {
  250. ResourceDictionaryTests.WindowStyle(),
  251. });
  252. return UnitTestApplication.Start(services);
  253. }
  254. private static Style WindowStyle()
  255. {
  256. return new Style(x => x.OfType<Window>())
  257. {
  258. Setters =
  259. {
  260. new Setter(
  261. Window.TemplateProperty,
  262. new FuncControlTemplate<Window>((x, scope) =>
  263. new ContentPresenter
  264. {
  265. Name = "PART_ContentPresenter",
  266. [!ContentPresenter.ContentProperty] = x[!Window.ContentProperty],
  267. }.RegisterInNameScope(scope)))
  268. }
  269. };
  270. }
  271. }
  272. }