SelectingItemsControlTests.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. // -----------------------------------------------------------------------
  2. // <copyright file="SelectingItemsControlTests.cs" company="Steven Kirk">
  3. // Copyright 2014 MIT Licence. See licence.md for more information.
  4. // </copyright>
  5. // -----------------------------------------------------------------------
  6. namespace Perspex.Controls.UnitTests.Primitives
  7. {
  8. using System.Collections.ObjectModel;
  9. using Perspex.Collections;
  10. using Perspex.Controls.Presenters;
  11. using Perspex.Controls.Primitives;
  12. using Perspex.Controls.Templates;
  13. using Perspex.Input;
  14. using Perspex.Interactivity;
  15. using Xunit;
  16. public class SelectingItemsControlTests
  17. {
  18. [Fact]
  19. public void SelectedIndex_Should_Initially_Be_Minus_1()
  20. {
  21. var items = new[]
  22. {
  23. new Item(),
  24. new Item(),
  25. };
  26. var target = new SelectingItemsControl
  27. {
  28. Items = items,
  29. Template = this.Template(),
  30. };
  31. Assert.Equal(-1, target.SelectedIndex);
  32. }
  33. [Fact]
  34. public void Item_IsSelected_Should_Initially_Be_False()
  35. {
  36. var items = new[]
  37. {
  38. new Item(),
  39. new Item(),
  40. };
  41. var target = new SelectingItemsControl
  42. {
  43. Items = items,
  44. Template = this.Template(),
  45. };
  46. target.ApplyTemplate();
  47. Assert.False(items[0].IsSelected);
  48. Assert.False(items[1].IsSelected);
  49. }
  50. [Fact]
  51. public void Setting_SelectedItem_Should_Set_Item_IsSelected_True()
  52. {
  53. var items = new[]
  54. {
  55. new Item(),
  56. new Item(),
  57. };
  58. var target = new SelectingItemsControl
  59. {
  60. Items = items,
  61. Template = this.Template(),
  62. };
  63. target.ApplyTemplate();
  64. target.SelectedItem = items[1];
  65. Assert.False(items[0].IsSelected);
  66. Assert.True(items[1].IsSelected);
  67. }
  68. [Fact]
  69. public void Setting_SelectedItem_Before_ApplyTemplate_Should_Set_Item_IsSelected_True()
  70. {
  71. var items = new[]
  72. {
  73. new Item(),
  74. new Item(),
  75. };
  76. var target = new SelectingItemsControl
  77. {
  78. Items = items,
  79. Template = this.Template(),
  80. };
  81. target.SelectedItem = items[1];
  82. target.ApplyTemplate();
  83. Assert.False(items[0].IsSelected);
  84. Assert.True(items[1].IsSelected);
  85. }
  86. [Fact]
  87. public void Setting_SelectedIndex_Before_ApplyTemplate_Should_Set_Item_IsSelected_True()
  88. {
  89. var items = new[]
  90. {
  91. new Item(),
  92. new Item(),
  93. };
  94. var target = new SelectingItemsControl
  95. {
  96. Items = items,
  97. Template = this.Template(),
  98. };
  99. target.SelectedIndex = 1;
  100. target.ApplyTemplate();
  101. Assert.False(items[0].IsSelected);
  102. Assert.True(items[1].IsSelected);
  103. }
  104. [Fact]
  105. public void Setting_SelectedItem_Should_Set_SelectedIndex()
  106. {
  107. var items = new[]
  108. {
  109. new Item(),
  110. new Item(),
  111. };
  112. var target = new SelectingItemsControl
  113. {
  114. Items = items,
  115. Template = this.Template(),
  116. };
  117. target.ApplyTemplate();
  118. target.SelectedItem = items[1];
  119. Assert.Equal(items[1], target.SelectedItem);
  120. Assert.Equal(1, target.SelectedIndex);
  121. }
  122. [Fact]
  123. public void Setting_SelectedItem_To_Not_Present_Item_Should_Clear_Selection()
  124. {
  125. var items = new[]
  126. {
  127. new Item(),
  128. new Item(),
  129. };
  130. var target = new SelectingItemsControl
  131. {
  132. Items = items,
  133. Template = this.Template(),
  134. };
  135. target.ApplyTemplate();
  136. target.SelectedItem = items[1];
  137. Assert.Equal(items[1], target.SelectedItem);
  138. Assert.Equal(1, target.SelectedIndex);
  139. target.SelectedItem = new Item();
  140. Assert.Equal(null, target.SelectedItem);
  141. Assert.Equal(-1, target.SelectedIndex);
  142. }
  143. [Fact]
  144. public void Setting_SelectedIndex_Should_Set_SelectedItem()
  145. {
  146. var items = new[]
  147. {
  148. new Item(),
  149. new Item(),
  150. };
  151. var target = new SelectingItemsControl
  152. {
  153. Items = items,
  154. Template = this.Template(),
  155. };
  156. target.ApplyTemplate();
  157. target.SelectedIndex = 1;
  158. Assert.Equal(items[1], target.SelectedItem);
  159. }
  160. [Fact]
  161. public void Setting_SelectedIndex_Out_Of_Bounds_Should_Clear_Selection()
  162. {
  163. var items = new[]
  164. {
  165. new Item(),
  166. new Item(),
  167. };
  168. var target = new SelectingItemsControl
  169. {
  170. Items = items,
  171. Template = this.Template(),
  172. };
  173. target.ApplyTemplate();
  174. target.SelectedIndex = 2;
  175. Assert.Equal(-1, target.SelectedIndex);
  176. }
  177. [Fact]
  178. public void Setting_SelectedItem_To_Non_Existent_Item_Should_Clear_Selection()
  179. {
  180. var target = new SelectingItemsControl
  181. {
  182. Template = this.Template(),
  183. };
  184. target.ApplyTemplate();
  185. target.SelectedItem = new Item();
  186. Assert.Equal(-1, target.SelectedIndex);
  187. Assert.Null(target.SelectedItem);
  188. }
  189. [Fact]
  190. public void Adding_Selected_Item_Should_Update_Selection()
  191. {
  192. var items = new PerspexList<Item>(new[]
  193. {
  194. new Item(),
  195. new Item(),
  196. });
  197. var target = new SelectingItemsControl
  198. {
  199. Items = items,
  200. Template = this.Template(),
  201. };
  202. target.ApplyTemplate();
  203. items.Add(new Item { IsSelected = true });
  204. Assert.Equal(2, target.SelectedIndex);
  205. Assert.Equal(items[2], target.SelectedItem);
  206. }
  207. [Fact]
  208. public void Setting_Items_To_Null_Should_Clear_Selection()
  209. {
  210. var items = new PerspexList<Item>
  211. {
  212. new Item(),
  213. new Item(),
  214. };
  215. var target = new SelectingItemsControl
  216. {
  217. Items = items,
  218. Template = this.Template(),
  219. };
  220. target.ApplyTemplate();
  221. target.SelectedIndex = 1;
  222. Assert.Equal(items[1], target.SelectedItem);
  223. Assert.Equal(1, target.SelectedIndex);
  224. target.Items = null;
  225. Assert.Equal(null, target.SelectedItem);
  226. Assert.Equal(-1, target.SelectedIndex);
  227. }
  228. [Fact]
  229. public void Removing_Selected_Item_Should_Clear_Selection()
  230. {
  231. var items = new PerspexList<Item>
  232. {
  233. new Item(),
  234. new Item(),
  235. };
  236. var target = new SelectingItemsControl
  237. {
  238. Items = items,
  239. Template = this.Template(),
  240. };
  241. target.ApplyTemplate();
  242. target.SelectedIndex = 1;
  243. Assert.Equal(items[1], target.SelectedItem);
  244. Assert.Equal(1, target.SelectedIndex);
  245. items.RemoveAt(1);
  246. Assert.Equal(null, target.SelectedItem);
  247. Assert.Equal(-1, target.SelectedIndex);
  248. }
  249. [Fact]
  250. public void Resetting_Items_Collection_Should_Clear_Selection()
  251. {
  252. // Need to use ObservableCollection here as PerspexList signals a Clear as an
  253. // add + remove.
  254. var items = new ObservableCollection<Item>
  255. {
  256. new Item(),
  257. new Item(),
  258. };
  259. var target = new SelectingItemsControl
  260. {
  261. Items = items,
  262. Template = this.Template(),
  263. };
  264. target.ApplyTemplate();
  265. target.SelectedIndex = 1;
  266. Assert.Equal(items[1], target.SelectedItem);
  267. Assert.Equal(1, target.SelectedIndex);
  268. items.Clear();
  269. Assert.Equal(null, target.SelectedItem);
  270. Assert.Equal(-1, target.SelectedIndex);
  271. }
  272. [Fact]
  273. public void Focusing_Item_With_Pointer_Should_Select_It()
  274. {
  275. var target = new SelectingItemsControl
  276. {
  277. Template = this.Template(),
  278. Items = new[] { "foo", "bar" },
  279. };
  280. target.ApplyTemplate();
  281. var e = new GotFocusEventArgs
  282. {
  283. RoutedEvent = InputElement.GotFocusEvent,
  284. NavigationMethod = NavigationMethod.Pointer,
  285. };
  286. target.Presenter.Panel.Children[1].RaiseEvent(e);
  287. Assert.Equal(1, target.SelectedIndex);
  288. // GotFocus should be raised on parent control.
  289. Assert.False(e.Handled);
  290. }
  291. [Fact]
  292. public void Focusing_Item_With_Directional_Keys_Should_Select_It()
  293. {
  294. var target = new SelectingItemsControl
  295. {
  296. Template = this.Template(),
  297. Items = new[] { "foo", "bar" },
  298. };
  299. target.ApplyTemplate();
  300. var e = new GotFocusEventArgs
  301. {
  302. RoutedEvent = InputElement.GotFocusEvent,
  303. NavigationMethod = NavigationMethod.Directional,
  304. };
  305. target.Presenter.Panel.Children[1].RaiseEvent(e);
  306. Assert.Equal(1, target.SelectedIndex);
  307. Assert.False(e.Handled);
  308. }
  309. [Fact]
  310. public void Focusing_Item_With_Tab_Should_Not_Select_It()
  311. {
  312. var target = new SelectingItemsControl
  313. {
  314. Template = this.Template(),
  315. Items = new[] { "foo", "bar" },
  316. };
  317. target.ApplyTemplate();
  318. var e = new GotFocusEventArgs
  319. {
  320. RoutedEvent = InputElement.GotFocusEvent,
  321. NavigationMethod = NavigationMethod.Tab,
  322. };
  323. target.Presenter.Panel.Children[1].RaiseEvent(e);
  324. Assert.Equal(-1, target.SelectedIndex);
  325. }
  326. [Fact]
  327. public void Raising_IsSelectedChanged_On_Item_Should_Update_Selection()
  328. {
  329. var items = new[]
  330. {
  331. new Item(),
  332. new Item(),
  333. };
  334. var target = new SelectingItemsControl
  335. {
  336. Items = items,
  337. Template = this.Template(),
  338. };
  339. target.ApplyTemplate();
  340. target.SelectedItem = items[1];
  341. Assert.False(items[0].IsSelected);
  342. Assert.True(items[1].IsSelected);
  343. items[0].IsSelected = true;
  344. items[0].RaiseEvent(new RoutedEventArgs(SelectingItemsControl.IsSelectedChangedEvent));
  345. Assert.Equal(0, target.SelectedIndex);
  346. Assert.Equal(items[0], target.SelectedItem);
  347. Assert.True(items[0].IsSelected);
  348. Assert.False(items[1].IsSelected);
  349. }
  350. [Fact]
  351. public void Clearing_IsSelected_And_Raising_IsSelectedChanged_On_Item_Should_Update_Selection()
  352. {
  353. var items = new[]
  354. {
  355. new Item(),
  356. new Item(),
  357. };
  358. var target = new SelectingItemsControl
  359. {
  360. Items = items,
  361. Template = this.Template(),
  362. };
  363. target.ApplyTemplate();
  364. target.SelectedItem = items[1];
  365. Assert.False(items[0].IsSelected);
  366. Assert.True(items[1].IsSelected);
  367. items[1].IsSelected = false;
  368. items[1].RaiseEvent(new RoutedEventArgs(SelectingItemsControl.IsSelectedChangedEvent));
  369. Assert.Equal(-1, target.SelectedIndex);
  370. Assert.Null(target.SelectedItem);
  371. }
  372. [Fact]
  373. public void Raising_IsSelectedChanged_On_Someone_Elses_Item_Should_Not_Update_Selection()
  374. {
  375. var items = new[]
  376. {
  377. new Item(),
  378. new Item(),
  379. };
  380. var target = new SelectingItemsControl
  381. {
  382. Items = items,
  383. Template = this.Template(),
  384. };
  385. target.ApplyTemplate();
  386. target.SelectedItem = items[1];
  387. var notChild = new Item
  388. {
  389. IsSelected = true,
  390. };
  391. target.RaiseEvent(new RoutedEventArgs
  392. {
  393. RoutedEvent = SelectingItemsControl.IsSelectedChangedEvent,
  394. Source = notChild,
  395. });
  396. Assert.Equal(target.SelectedItem, items[1]);
  397. }
  398. private ControlTemplate Template()
  399. {
  400. return new ControlTemplate<SelectingItemsControl>(control =>
  401. new ItemsPresenter
  402. {
  403. Name = "itemsPresenter",
  404. [~ItemsPresenter.ItemsProperty] = control[~ListBox.ItemsProperty],
  405. [~ItemsPresenter.ItemsPanelProperty] = control[~ListBox.ItemsPanelProperty],
  406. });
  407. }
  408. private class Item : Control, ISelectable
  409. {
  410. public bool IsSelected { get; set; }
  411. }
  412. }
  413. }