ItemsControlTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  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.Specialized;
  4. using System.Linq;
  5. using Perspex.Collections;
  6. using Perspex.Controls.Presenters;
  7. using Perspex.Controls.Templates;
  8. using Perspex.LogicalTree;
  9. using Perspex.Styling;
  10. using Perspex.VisualTree;
  11. using Xunit;
  12. namespace Perspex.Controls.UnitTests
  13. {
  14. public class ItemsControlTests
  15. {
  16. [Fact]
  17. public void Panel_Should_Have_TemplatedParent_Set_To_ItemsControl()
  18. {
  19. var target = new ItemsControl();
  20. target.Template = GetTemplate();
  21. target.Items = new[] { "Foo" };
  22. target.ApplyTemplate();
  23. var presenter = target.GetTemplateChildren().OfType<ItemsPresenter>().Single();
  24. var panel = target.GetTemplateChildren().OfType<StackPanel>().Single();
  25. Assert.Equal(target, panel.TemplatedParent);
  26. }
  27. [Fact]
  28. public void Item_Should_Have_TemplatedParent_Set_To_Null()
  29. {
  30. var target = new ItemsControl();
  31. target.Template = GetTemplate();
  32. target.Items = new[] { "Foo" };
  33. target.ApplyTemplate();
  34. var presenter = target.GetTemplateChildren().OfType<ItemsPresenter>().Single();
  35. var panel = target.GetTemplateChildren().OfType<StackPanel>().Single();
  36. var item = (TextBlock)panel.GetVisualChildren().First();
  37. Assert.Null(item.TemplatedParent);
  38. }
  39. [Fact]
  40. public void Control_Item_Should_Have_Parent_Set()
  41. {
  42. var target = new ItemsControl();
  43. var child = new Control();
  44. target.Template = GetTemplate();
  45. target.Items = new[] { child };
  46. target.ApplyTemplate();
  47. Assert.Equal(target, child.Parent);
  48. Assert.Equal(target, ((ILogical)child).LogicalParent);
  49. }
  50. [Fact]
  51. public void Clearing_Control_Item_Should_Clear_Child_Controls_Parent()
  52. {
  53. var target = new ItemsControl();
  54. var child = new Control();
  55. target.Template = GetTemplate();
  56. target.Items = new[] { child };
  57. target.ApplyTemplate();
  58. target.Items = null;
  59. Assert.Null(child.Parent);
  60. Assert.Null(((ILogical)child).LogicalParent);
  61. }
  62. [Fact]
  63. public void Adding_Control_Item_Should_Make_Control_Appear_In_LogicalChildren()
  64. {
  65. var target = new ItemsControl();
  66. var child = new Control();
  67. target.Template = GetTemplate();
  68. target.Items = new[] { child };
  69. target.ApplyTemplate();
  70. Assert.Equal(new[] { child }, ((ILogical)target).LogicalChildren.ToList());
  71. }
  72. [Fact]
  73. public void Adding_String_Item_Should_Make_TextBlock_Appear_In_LogicalChildren()
  74. {
  75. var target = new ItemsControl();
  76. var child = new Control();
  77. target.Template = GetTemplate();
  78. target.Items = new[] { "Foo" };
  79. target.ApplyTemplate();
  80. var logical = (ILogical)target;
  81. Assert.Equal(1, logical.LogicalChildren.Count);
  82. Assert.IsType<TextBlock>(logical.LogicalChildren[0]);
  83. }
  84. [Fact]
  85. public void Setting_Items_To_Null_Should_Remove_LogicalChildren()
  86. {
  87. var target = new ItemsControl();
  88. var child = new Control();
  89. target.Template = GetTemplate();
  90. target.Items = new[] { "Foo" };
  91. target.ApplyTemplate();
  92. target.Items = null;
  93. Assert.Equal(new ILogical[0], ((ILogical)target).LogicalChildren.ToList());
  94. }
  95. [Fact]
  96. public void Setting_Items_Should_Fire_LogicalChildren_CollectionChanged()
  97. {
  98. var target = new ItemsControl();
  99. var child = new Control();
  100. var called = false;
  101. target.Template = GetTemplate();
  102. target.ApplyTemplate();
  103. ((ILogical)target).LogicalChildren.CollectionChanged += (s, e) =>
  104. called = e.Action == NotifyCollectionChangedAction.Add;
  105. target.Items = new[] { child };
  106. Assert.True(called);
  107. }
  108. [Fact]
  109. public void Setting_Items_To_Null_Should_Fire_LogicalChildren_CollectionChanged()
  110. {
  111. var target = new ItemsControl();
  112. var child = new Control();
  113. var called = false;
  114. target.Template = GetTemplate();
  115. target.Items = new[] { child };
  116. target.ApplyTemplate();
  117. ((ILogical)target).LogicalChildren.CollectionChanged += (s, e) =>
  118. called = e.Action == NotifyCollectionChangedAction.Remove;
  119. target.Items = null;
  120. Assert.True(called);
  121. }
  122. [Fact]
  123. public void Changing_Items_Should_Fire_LogicalChildren_CollectionChanged()
  124. {
  125. var target = new ItemsControl();
  126. var child = new Control();
  127. var called = false;
  128. target.Template = GetTemplate();
  129. target.Items = new[] { child };
  130. target.ApplyTemplate();
  131. ((ILogical)target).LogicalChildren.CollectionChanged += (s, e) => called = true;
  132. target.Items = new[] { "Foo" };
  133. Assert.True(called);
  134. }
  135. [Fact]
  136. public void Adding_Items_Should_Fire_LogicalChildren_CollectionChanged()
  137. {
  138. var target = new ItemsControl();
  139. var items = new PerspexList<string> { "Foo" };
  140. var called = false;
  141. target.Template = GetTemplate();
  142. target.Items = items;
  143. target.ApplyTemplate();
  144. ((ILogical)target).LogicalChildren.CollectionChanged += (s, e) =>
  145. called = e.Action == NotifyCollectionChangedAction.Add;
  146. items.Add("Bar");
  147. Assert.True(called);
  148. }
  149. [Fact]
  150. public void Removing_Items_Should_Fire_LogicalChildren_CollectionChanged()
  151. {
  152. var target = new ItemsControl();
  153. var items = new PerspexList<string> { "Foo", "Bar" };
  154. var called = false;
  155. target.Template = GetTemplate();
  156. target.Items = items;
  157. target.ApplyTemplate();
  158. ((ILogical)target).LogicalChildren.CollectionChanged += (s, e) =>
  159. called = e.Action == NotifyCollectionChangedAction.Remove;
  160. items.Remove("Bar");
  161. Assert.True(called);
  162. }
  163. [Fact]
  164. public void LogicalChildren_Should_Not_Change_Instance_When_Template_Changed()
  165. {
  166. var target = new ItemsControl()
  167. {
  168. Template = GetTemplate(),
  169. };
  170. var before = ((ILogical)target).LogicalChildren;
  171. target.Template = null;
  172. target.Template = GetTemplate();
  173. var after = ((ILogical)target).LogicalChildren;
  174. Assert.NotNull(before);
  175. Assert.NotNull(after);
  176. Assert.Same(before, after);
  177. }
  178. [Fact]
  179. public void Empty_Class_Should_Initially_Be_Applied()
  180. {
  181. var target = new ItemsControl()
  182. {
  183. Template = GetTemplate(),
  184. };
  185. Assert.True(target.Classes.Contains(":empty"));
  186. }
  187. [Fact]
  188. public void Empty_Class_Should_Be_Cleared_When_Items_Added()
  189. {
  190. var target = new ItemsControl()
  191. {
  192. Template = GetTemplate(),
  193. Items = new[] { 1, 2, 3 },
  194. };
  195. Assert.False(target.Classes.Contains(":empty"));
  196. }
  197. [Fact]
  198. public void Empty_Class_Should_Be_Set_When_Empty_Collection_Set()
  199. {
  200. var target = new ItemsControl()
  201. {
  202. Template = GetTemplate(),
  203. Items = new[] { 1, 2, 3 },
  204. };
  205. target.Items = new int[0];
  206. Assert.True(target.Classes.Contains(":empty"));
  207. }
  208. [Fact]
  209. public void Setting_Presenter_Explicitly_Should_Set_Item_Parent()
  210. {
  211. var target = new TestItemsControl();
  212. var child = new Control();
  213. var presenter = new ItemsPresenter
  214. {
  215. TemplatedParent = target,
  216. [~ItemsPresenter.ItemsProperty] = target[~ItemsControl.ItemsProperty],
  217. };
  218. presenter.ApplyTemplate();
  219. target.Presenter = presenter;
  220. target.Items = new[] { child };
  221. target.ApplyTemplate();
  222. Assert.Equal(target, child.Parent);
  223. Assert.Equal(target, ((ILogical)child).LogicalParent);
  224. }
  225. [Fact]
  226. public void DataContexts_Should_Be_Correctly_Set()
  227. {
  228. var items = new object[]
  229. {
  230. "Foo",
  231. new Item("Bar"),
  232. new TextBlock { Text = "Baz" },
  233. new ListBoxItem { Content = "Qux" },
  234. };
  235. var target = new ItemsControl
  236. {
  237. Template = GetTemplate(),
  238. DataContext = "Base",
  239. DataTemplates = new DataTemplates
  240. {
  241. new DataTemplate<Item>(x => new Button { Content = x })
  242. },
  243. Items = items,
  244. };
  245. target.ApplyTemplate();
  246. var dataContexts = target.Presenter.Panel.Children
  247. .Cast<Control>()
  248. .Select(x => x.DataContext)
  249. .ToList();
  250. Assert.Equal(
  251. new object[] { items[0], items[1], "Base", "Base" },
  252. dataContexts);
  253. }
  254. [Fact]
  255. public void MemberSelector_Should_Select_Member()
  256. {
  257. var target = new ItemsControl
  258. {
  259. Template = GetTemplate(),
  260. Items = new[] { new Item("Foo"), new Item("Bar") },
  261. MemberSelector = new FuncMemberSelector<Item, string>(x => x.Value),
  262. };
  263. target.ApplyTemplate();
  264. var text = target.Presenter.Panel.Children
  265. .Cast<TextBlock>()
  266. .Select(x => x.Text)
  267. .ToList();
  268. Assert.Equal(new[] { "Foo", "Bar" }, text);
  269. }
  270. private class Item
  271. {
  272. public Item(string value)
  273. {
  274. Value = value;
  275. }
  276. public string Value { get; }
  277. }
  278. private ControlTemplate GetTemplate()
  279. {
  280. return new ControlTemplate<ItemsControl>(parent =>
  281. {
  282. return new Border
  283. {
  284. Background = new Media.SolidColorBrush(0xffffffff),
  285. Child = new ItemsPresenter
  286. {
  287. Name = "itemsPresenter",
  288. MemberSelector = parent.MemberSelector,
  289. [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty],
  290. }
  291. };
  292. });
  293. }
  294. private class TestItemsControl : ItemsControl
  295. {
  296. public new IItemsPresenter Presenter
  297. {
  298. get { return base.Presenter; }
  299. set { base.Presenter = value; }
  300. }
  301. }
  302. }
  303. }