TreeViewTests.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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.Collections.Generic;
  4. using System.Linq;
  5. using Perspex.Controls.Presenters;
  6. using Perspex.Controls.Templates;
  7. using Perspex.Input;
  8. using Perspex.LogicalTree;
  9. using Xunit;
  10. namespace Perspex.Controls.UnitTests
  11. {
  12. public class TreeViewTests
  13. {
  14. [Fact]
  15. public void Items_Should_Be_Created()
  16. {
  17. var target = new TreeView
  18. {
  19. Template = CreateTreeViewTemplate(),
  20. Items = CreateTestTreeData(),
  21. DataTemplates = CreateNodeDataTemplate(),
  22. };
  23. target.ApplyTemplate();
  24. Assert.Equal(new[] { "Root" }, ExtractItemHeader(target, 0));
  25. Assert.Equal(new[] { "Child1", "Child2" }, ExtractItemHeader(target, 1));
  26. Assert.Equal(new[] { "Grandchild2a" }, ExtractItemHeader(target, 2));
  27. }
  28. [Fact]
  29. public void Root_ItemContainerGenerator_Containers_Should_Be_Root_Containers()
  30. {
  31. var target = new TreeView
  32. {
  33. Template = CreateTreeViewTemplate(),
  34. Items = CreateTestTreeData(),
  35. DataTemplates = CreateNodeDataTemplate(),
  36. };
  37. target.ApplyTemplate();
  38. var container = (TreeViewItem)target.ItemContainerGenerator.Containers.Single();
  39. var header = (TextBlock)container.Header;
  40. Assert.Equal("Root", header.Text);
  41. }
  42. [Fact]
  43. public void Root_TreeContainerFromItem_Should_Return_Descendent_Item()
  44. {
  45. var tree = CreateTestTreeData();
  46. var target = new TreeView
  47. {
  48. Template = CreateTreeViewTemplate(),
  49. Items = tree,
  50. DataTemplates = CreateNodeDataTemplate(),
  51. };
  52. // For TreeViewItem to find its parent TreeView, OnAttachedToVisualTree needs
  53. // to be called, which requires an IRenderRoot.
  54. var visualRoot = new TestRoot();
  55. visualRoot.Child = target;
  56. ApplyTemplates(target);
  57. var container = target.ItemContainerGenerator.TreeContainerFromItem(
  58. tree[0].Children[1].Children[0]);
  59. var header = ((TreeViewItem)container).Header;
  60. var headerContent = ((TextBlock)header).Text;
  61. Assert.Equal("Grandchild2a", headerContent);
  62. }
  63. [Fact]
  64. public void Clicking_Item_Should_Select_It()
  65. {
  66. var tree = CreateTestTreeData();
  67. var target = new TreeView
  68. {
  69. Template = CreateTreeViewTemplate(),
  70. Items = tree,
  71. DataTemplates = CreateNodeDataTemplate(),
  72. };
  73. var visualRoot = new TestRoot();
  74. visualRoot.Child = target;
  75. ApplyTemplates(target);
  76. var item = tree[0].Children[1].Children[0];
  77. var container = (TreeViewItem)target.ItemContainerGenerator.TreeContainerFromItem(item);
  78. container.RaiseEvent(new PointerPressEventArgs
  79. {
  80. RoutedEvent = InputElement.PointerPressedEvent,
  81. MouseButton = MouseButton.Left,
  82. });
  83. Assert.Equal(item, target.SelectedItem);
  84. Assert.True(container.IsSelected);
  85. }
  86. [Fact]
  87. public void LogicalChildren_Should_Be_Set()
  88. {
  89. var target = new TreeView
  90. {
  91. Template = CreateTreeViewTemplate(),
  92. Items = new[] { "Foo", "Bar", "Baz " },
  93. };
  94. target.ApplyTemplate();
  95. var result = target.GetLogicalChildren()
  96. .OfType<TreeViewItem>()
  97. .Select(x => x.Header)
  98. .OfType<TextBlock>()
  99. .Select(x => x.Text)
  100. .ToList();
  101. Assert.Equal(new[] { "Foo", "Bar", "Baz " }, result);
  102. }
  103. [Fact]
  104. public void DataContexts_Should_Be_Correctly_Set()
  105. {
  106. var items = new object[]
  107. {
  108. "Foo",
  109. new Node { Value = "Bar" },
  110. new TextBlock { Text = "Baz" },
  111. new TreeViewItem { Header = "Qux" },
  112. };
  113. var target = new TreeView
  114. {
  115. Template = CreateTreeViewTemplate(),
  116. DataContext = "Base",
  117. DataTemplates = new DataTemplates
  118. {
  119. new FuncDataTemplate<Node>(x => new Button { Content = x })
  120. },
  121. Items = items,
  122. };
  123. target.ApplyTemplate();
  124. var dataContexts = target.Presenter.Panel.Children
  125. .Cast<Control>()
  126. .Select(x => x.DataContext)
  127. .ToList();
  128. Assert.Equal(
  129. new object[] { items[0], items[1], "Base", "Base" },
  130. dataContexts);
  131. }
  132. private void ApplyTemplates(TreeView tree)
  133. {
  134. tree.ApplyTemplate();
  135. ApplyTemplates(tree.Presenter.Panel.Children);
  136. }
  137. private void ApplyTemplates(IEnumerable<IControl> controls)
  138. {
  139. foreach (TreeViewItem control in controls)
  140. {
  141. control.Template = CreateTreeViewItemTemplate();
  142. control.ApplyTemplate();
  143. ApplyTemplates(control.Presenter.Panel.Children);
  144. }
  145. }
  146. private IList<Node> CreateTestTreeData()
  147. {
  148. return new[]
  149. {
  150. new Node
  151. {
  152. Value = "Root",
  153. Children = new[]
  154. {
  155. new Node
  156. {
  157. Value = "Child1",
  158. },
  159. new Node
  160. {
  161. Value = "Child2",
  162. Children = new[]
  163. {
  164. new Node
  165. {
  166. Value = "Grandchild2a",
  167. },
  168. },
  169. },
  170. }
  171. }
  172. };
  173. }
  174. private DataTemplates CreateNodeDataTemplate()
  175. {
  176. return new DataTemplates
  177. {
  178. new FuncTreeDataTemplate<Node>(
  179. x => new TextBlock { Text = x.Value },
  180. x => x.Children),
  181. };
  182. }
  183. private ControlTemplate CreateTreeViewTemplate()
  184. {
  185. return new ControlTemplate<TreeView>(parent => new ItemsPresenter
  186. {
  187. Name = "itemsPresenter",
  188. [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
  189. });
  190. }
  191. private ControlTemplate CreateTreeViewItemTemplate()
  192. {
  193. return new ControlTemplate<TreeViewItem>(parent => new ItemsPresenter
  194. {
  195. Name = "itemsPresenter",
  196. [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
  197. });
  198. }
  199. private List<string> ExtractItemHeader(TreeView tree, int level)
  200. {
  201. return ExtractItemContent(tree.Presenter.Panel, 0, level)
  202. .Select(x => x.Header)
  203. .OfType<TextBlock>()
  204. .Select(x => x.Text)
  205. .ToList();
  206. }
  207. private IEnumerable<TreeViewItem> ExtractItemContent(IPanel panel, int currentLevel, int level)
  208. {
  209. foreach (TreeViewItem container in panel.Children)
  210. {
  211. if (container.Template == null)
  212. {
  213. container.Template = CreateTreeViewItemTemplate();
  214. container.ApplyTemplate();
  215. }
  216. if (currentLevel == level)
  217. {
  218. yield return container;
  219. }
  220. else
  221. {
  222. foreach (var child in ExtractItemContent(container.Presenter.Panel, currentLevel + 1, level))
  223. {
  224. yield return child;
  225. }
  226. }
  227. }
  228. }
  229. private class Node
  230. {
  231. public string Value { get; set; }
  232. public IList<Node> Children { get; set; }
  233. }
  234. }
  235. }