TemplatedControlTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // Copyright (c) The Perspex 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.Collections.Generic;
  5. using System.Linq;
  6. using Moq;
  7. using Perspex.Controls.Presenters;
  8. using Perspex.Controls.Primitives;
  9. using Perspex.Controls.Templates;
  10. using Perspex.LogicalTree;
  11. using Perspex.Styling;
  12. using Perspex.UnitTests;
  13. using Perspex.VisualTree;
  14. using Xunit;
  15. namespace Perspex.Controls.UnitTests.Primitives
  16. {
  17. public class TemplatedControlTests
  18. {
  19. [Fact]
  20. public void Template_Doesnt_Get_Executed_On_Set()
  21. {
  22. bool executed = false;
  23. var template = new FuncControlTemplate(_ =>
  24. {
  25. executed = true;
  26. return new Control();
  27. });
  28. var target = new TemplatedControl
  29. {
  30. Template = template,
  31. };
  32. Assert.False(executed);
  33. }
  34. [Fact]
  35. public void Template_Gets_Executed_On_Measure()
  36. {
  37. bool executed = false;
  38. var template = new FuncControlTemplate(_ =>
  39. {
  40. executed = true;
  41. return new Control();
  42. });
  43. var target = new TemplatedControl
  44. {
  45. Template = template,
  46. };
  47. target.Measure(new Size(100, 100));
  48. Assert.True(executed);
  49. }
  50. [Fact]
  51. public void ApplyTemplate_Should_Create_Visual_Children()
  52. {
  53. var target = new TemplatedControl
  54. {
  55. Template = new FuncControlTemplate(_ => new Decorator
  56. {
  57. Child = new Panel
  58. {
  59. Children = new Controls
  60. {
  61. new TextBlock(),
  62. new Border(),
  63. }
  64. }
  65. }),
  66. };
  67. target.ApplyTemplate();
  68. var types = target.GetVisualDescendents().Select(x => x.GetType()).ToList();
  69. Assert.Equal(
  70. new[]
  71. {
  72. typeof(Decorator),
  73. typeof(Panel),
  74. typeof(TextBlock),
  75. typeof(Border)
  76. },
  77. types);
  78. Assert.Empty(target.GetLogicalChildren());
  79. }
  80. [Fact]
  81. public void Templated_Child_Should_Be_NameScope()
  82. {
  83. var target = new TemplatedControl
  84. {
  85. Template = new FuncControlTemplate(_ => new Decorator
  86. {
  87. Child = new Panel
  88. {
  89. Children = new Controls
  90. {
  91. new TextBlock(),
  92. new Border(),
  93. }
  94. }
  95. }),
  96. };
  97. target.ApplyTemplate();
  98. Assert.NotNull(NameScope.GetNameScope((Control)target.GetVisualChildren().Single()));
  99. }
  100. [Fact]
  101. public void Templated_Children_Should_Have_TemplatedParent_Set()
  102. {
  103. var target = new TemplatedControl
  104. {
  105. Template = new FuncControlTemplate(_ => new Decorator
  106. {
  107. Child = new Panel
  108. {
  109. Children = new Controls
  110. {
  111. new TextBlock(),
  112. new Border(),
  113. }
  114. }
  115. }),
  116. };
  117. target.ApplyTemplate();
  118. var templatedParents = target.GetVisualDescendents()
  119. .OfType<IControl>()
  120. .Select(x => x.TemplatedParent)
  121. .ToList();
  122. Assert.Equal(4, templatedParents.Count);
  123. Assert.True(templatedParents.All(x => x == target));
  124. }
  125. [Fact]
  126. public void Templated_Child_Should_Have_Parent_Set()
  127. {
  128. var target = new TemplatedControl
  129. {
  130. Template = new FuncControlTemplate(_ => new Decorator())
  131. };
  132. target.ApplyTemplate();
  133. var child = (Decorator)target.GetVisualChildren().Single();
  134. Assert.Equal(target, child.Parent);
  135. Assert.Equal(target, child.GetLogicalParent());
  136. }
  137. [Fact]
  138. public void Nested_Templated_Control_Should_Not_Have_Template_Applied()
  139. {
  140. var target = new TemplatedControl
  141. {
  142. Template = new FuncControlTemplate(_ => new ScrollViewer())
  143. };
  144. target.ApplyTemplate();
  145. var child = (ScrollViewer)target.GetVisualChildren().Single();
  146. Assert.Empty(child.GetVisualChildren());
  147. }
  148. [Fact]
  149. public void Templated_Children_Should_Be_Styled()
  150. {
  151. using (UnitTestApplication.Start(TestServices.MockStyler))
  152. {
  153. TestTemplatedControl target;
  154. var root = new TestRoot
  155. {
  156. Child = target = new TestTemplatedControl
  157. {
  158. Template = new FuncControlTemplate(_ =>
  159. {
  160. return new StackPanel
  161. {
  162. Children = new Controls
  163. {
  164. new TextBlock
  165. {
  166. }
  167. }
  168. };
  169. }),
  170. }
  171. };
  172. target.ApplyTemplate();
  173. var styler = Mock.Get(UnitTestApplication.Current.Services.Styler);
  174. styler.Verify(x => x.ApplyStyles(It.IsAny<TestTemplatedControl>()), Times.Once());
  175. styler.Verify(x => x.ApplyStyles(It.IsAny<StackPanel>()), Times.Once());
  176. styler.Verify(x => x.ApplyStyles(It.IsAny<TextBlock>()), Times.Once());
  177. }
  178. }
  179. [Fact]
  180. public void Nested_Templated_Controls_Have_Correct_TemplatedParent()
  181. {
  182. var target = new TestTemplatedControl
  183. {
  184. Template = new FuncControlTemplate(_ =>
  185. {
  186. return new ContentControl
  187. {
  188. Template = new FuncControlTemplate(parent =>
  189. {
  190. return new Border
  191. {
  192. Child = new ContentPresenter
  193. {
  194. [~ContentPresenter.ContentProperty] = parent.GetObservable(ContentControl.ContentProperty),
  195. }
  196. };
  197. }),
  198. Content = new Decorator
  199. {
  200. Child = new TextBlock()
  201. }
  202. };
  203. }),
  204. };
  205. target.ApplyTemplate();
  206. var contentControl = target.GetTemplateChildren().OfType<ContentControl>().Single();
  207. contentControl.ApplyTemplate();
  208. var border = contentControl.GetTemplateChildren().OfType<Border>().Single();
  209. var presenter = contentControl.GetTemplateChildren().OfType<ContentPresenter>().Single();
  210. var decorator = (Decorator)presenter.Content;
  211. var textBlock = (TextBlock)decorator.Child;
  212. Assert.Equal(target, contentControl.TemplatedParent);
  213. Assert.Equal(contentControl, border.TemplatedParent);
  214. Assert.Equal(contentControl, presenter.TemplatedParent);
  215. Assert.Equal(target, decorator.TemplatedParent);
  216. Assert.Equal(target, textBlock.TemplatedParent);
  217. }
  218. [Fact]
  219. public void Nested_TemplatedControls_Should_Register_With_Correct_NameScope()
  220. {
  221. var target = new ContentControl
  222. {
  223. Template = new FuncControlTemplate<ContentControl>(ScrollingContentControlTemplate),
  224. Content = "foo"
  225. };
  226. var root = new TestRoot { Child = target };
  227. target.ApplyTemplate();
  228. var border = target.GetVisualChildren().FirstOrDefault();
  229. Assert.IsType<Border>(border);
  230. var scrollViewer = border.GetVisualChildren().FirstOrDefault();
  231. Assert.IsType<ScrollViewer>(scrollViewer);
  232. ((ScrollViewer)scrollViewer).ApplyTemplate();
  233. var scrollContentPresenter = scrollViewer.GetVisualChildren().FirstOrDefault();
  234. Assert.IsType<ScrollContentPresenter>(scrollContentPresenter);
  235. ((ContentPresenter)scrollContentPresenter).UpdateChild();
  236. var contentPresenter = scrollContentPresenter.GetVisualChildren().FirstOrDefault();
  237. Assert.IsType<ContentPresenter>(contentPresenter);
  238. var borderNs = NameScope.GetNameScope((Control)border);
  239. var scrollContentPresenterNs = NameScope.GetNameScope((Control)scrollContentPresenter);
  240. Assert.NotNull(borderNs);
  241. Assert.Same(scrollViewer, borderNs.Find("ScrollViewer"));
  242. Assert.Same(contentPresenter, borderNs.Find("PART_ContentPresenter"));
  243. Assert.Same(scrollContentPresenter, scrollContentPresenterNs.Find("PART_ContentPresenter"));
  244. }
  245. [Fact]
  246. public void ApplyTemplate_Should_Raise_TemplateApplied()
  247. {
  248. var target = new TestTemplatedControl
  249. {
  250. Template = new FuncControlTemplate(_ => new Decorator())
  251. };
  252. var raised = false;
  253. target.TemplateApplied += (s, e) =>
  254. {
  255. Assert.Equal(TemplatedControl.TemplateAppliedEvent, e.RoutedEvent);
  256. Assert.Same(target, e.Source);
  257. Assert.NotNull(e.NameScope);
  258. raised = true;
  259. };
  260. target.ApplyTemplate();
  261. Assert.True(raised);
  262. }
  263. private static IControl ScrollingContentControlTemplate(ContentControl control)
  264. {
  265. return new Border
  266. {
  267. Child = new ScrollViewer
  268. {
  269. Template = new FuncControlTemplate<ScrollViewer>(ScrollViewerTemplate),
  270. Name = "ScrollViewer",
  271. Content = new ContentPresenter
  272. {
  273. Name = "PART_ContentPresenter",
  274. [!ContentPresenter.ContentProperty] = control[!ContentControl.ContentProperty],
  275. }
  276. }
  277. };
  278. }
  279. private static Control ScrollViewerTemplate(ScrollViewer control)
  280. {
  281. var result = new ScrollContentPresenter
  282. {
  283. Name = "PART_ContentPresenter",
  284. [~ContentPresenter.ContentProperty] = control[~ContentControl.ContentProperty],
  285. };
  286. return result;
  287. }
  288. }
  289. }