ListBoxTests_Multiple.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using Avalonia.Controls.Presenters;
  4. using Avalonia.Controls.Primitives;
  5. using Avalonia.Controls.Templates;
  6. using Avalonia.Input;
  7. using Avalonia.Input.Platform;
  8. using Avalonia.Styling;
  9. using Avalonia.UnitTests;
  10. using Avalonia.VisualTree;
  11. using Moq;
  12. using Xunit;
  13. namespace Avalonia.Controls.UnitTests
  14. {
  15. public class ListBoxTests_Multiple
  16. {
  17. private MouseTestHelper _helper = new MouseTestHelper();
  18. [Fact]
  19. public void Shift_Selecting_From_No_Selection_Selects_From_Start()
  20. {
  21. using (UnitTestApplication.Start())
  22. {
  23. var target = new ListBox
  24. {
  25. Template = new FuncControlTemplate(CreateListBoxTemplate),
  26. ItemsSource = new[] { "Foo", "Bar", "Baz" },
  27. SelectionMode = SelectionMode.Multiple,
  28. Width = 100,
  29. Height = 100,
  30. };
  31. var root = new TestRoot(target);
  32. root.LayoutManager.ExecuteInitialLayoutPass();
  33. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  34. _helper.Click(target.Presenter.Panel.Children[2], modifiers: KeyModifiers.Shift);
  35. Assert.Equal(new[] { "Foo", "Bar", "Baz" }, target.SelectedItems);
  36. Assert.Equal(new[] { 0, 1, 2 }, SelectedContainers(target));
  37. }
  38. }
  39. [Fact]
  40. public void Ctrl_Selecting_Raises_SelectionChanged_Events()
  41. {
  42. using (UnitTestApplication.Start())
  43. {
  44. var target = new ListBox
  45. {
  46. Template = new FuncControlTemplate(CreateListBoxTemplate),
  47. ItemsSource = new[] { "Foo", "Bar", "Baz", "Qux" },
  48. SelectionMode = SelectionMode.Multiple,
  49. Width = 100,
  50. Height = 100,
  51. };
  52. var root = new TestRoot(target);
  53. root.LayoutManager.ExecuteInitialLayoutPass();
  54. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  55. SelectionChangedEventArgs receivedArgs = null;
  56. target.SelectionChanged += (_, args) => receivedArgs = args;
  57. void VerifyAdded(string selection)
  58. {
  59. Assert.NotNull(receivedArgs);
  60. Assert.Equal(new[] { selection }, receivedArgs.AddedItems);
  61. Assert.Empty(receivedArgs.RemovedItems);
  62. }
  63. void VerifyRemoved(string selection)
  64. {
  65. Assert.NotNull(receivedArgs);
  66. Assert.Equal(new[] { selection }, receivedArgs.RemovedItems);
  67. Assert.Empty(receivedArgs.AddedItems);
  68. }
  69. _helper.Click(target.Presenter.Panel.Children[1]);
  70. VerifyAdded("Bar");
  71. receivedArgs = null;
  72. _helper.Click(target.Presenter.Panel.Children[2], modifiers: KeyModifiers.Control);
  73. VerifyAdded("Baz");
  74. receivedArgs = null;
  75. _helper.Click(target.Presenter.Panel.Children[3], modifiers: KeyModifiers.Control);
  76. VerifyAdded("Qux");
  77. receivedArgs = null;
  78. _helper.Click(target.Presenter.Panel.Children[1], modifiers: KeyModifiers.Control);
  79. VerifyRemoved("Bar");
  80. }
  81. }
  82. [Fact]
  83. public void Ctrl_Selecting_SelectedItem_With_Multiple_Selection_Active_Sets_SelectedItem_To_Next_Selection()
  84. {
  85. using (UnitTestApplication.Start())
  86. {
  87. var target = new ListBox
  88. {
  89. Template = new FuncControlTemplate(CreateListBoxTemplate),
  90. ItemsSource = new[] { "Foo", "Bar", "Baz", "Qux" },
  91. SelectionMode = SelectionMode.Multiple,
  92. Width = 100,
  93. Height = 100,
  94. };
  95. var root = new TestRoot(target);
  96. root.LayoutManager.ExecuteInitialLayoutPass();
  97. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  98. _helper.Click(target.Presenter.Panel.Children[1]);
  99. _helper.Click(target.Presenter.Panel.Children[2], modifiers: KeyModifiers.Control);
  100. _helper.Click(target.Presenter.Panel.Children[3], modifiers: KeyModifiers.Control);
  101. Assert.Equal(1, target.SelectedIndex);
  102. Assert.Equal("Bar", target.SelectedItem);
  103. Assert.Equal(new[] { "Bar", "Baz", "Qux" }, target.SelectedItems);
  104. _helper.Click(target.Presenter.Panel.Children[1], modifiers: KeyModifiers.Control);
  105. Assert.Equal(2, target.SelectedIndex);
  106. Assert.Equal("Baz", target.SelectedItem);
  107. Assert.Equal(new[] { "Baz", "Qux" }, target.SelectedItems);
  108. }
  109. }
  110. [Fact]
  111. public void Ctrl_Selecting_Non_SelectedItem_With_Multiple_Selection_Active_Leaves_SelectedItem_The_Same()
  112. {
  113. using (UnitTestApplication.Start())
  114. {
  115. var target = new ListBox
  116. {
  117. Template = new FuncControlTemplate(CreateListBoxTemplate),
  118. ItemsSource = new[] { "Foo", "Bar", "Baz" },
  119. SelectionMode = SelectionMode.Multiple,
  120. Width = 100,
  121. Height = 100,
  122. };
  123. var root = new TestRoot(target);
  124. root.LayoutManager.ExecuteInitialLayoutPass();
  125. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  126. _helper.Click(target.Presenter.Panel.Children[1]);
  127. _helper.Click(target.Presenter.Panel.Children[2], modifiers: KeyModifiers.Control);
  128. Assert.Equal(1, target.SelectedIndex);
  129. Assert.Equal("Bar", target.SelectedItem);
  130. _helper.Click(target.Presenter.Panel.Children[2], modifiers: KeyModifiers.Control);
  131. Assert.Equal(1, target.SelectedIndex);
  132. Assert.Equal("Bar", target.SelectedItem);
  133. }
  134. }
  135. [Fact]
  136. public void Should_Ctrl_Select_Correct_Item_When_Duplicate_Items_Are_Present()
  137. {
  138. using (UnitTestApplication.Start())
  139. {
  140. var target = new ListBox
  141. {
  142. Template = new FuncControlTemplate(CreateListBoxTemplate),
  143. ItemsSource = new[] { "Foo", "Bar", "Baz", "Foo", "Bar", "Baz" },
  144. SelectionMode = SelectionMode.Multiple,
  145. Width = 100,
  146. Height = 100,
  147. };
  148. var root = new TestRoot(target);
  149. root.LayoutManager.ExecuteInitialLayoutPass();
  150. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  151. _helper.Click(target.Presenter.Panel.Children[3]);
  152. _helper.Click(target.Presenter.Panel.Children[4], modifiers: KeyModifiers.Control);
  153. var panel = target.Presenter.Panel;
  154. Assert.Equal(new[] { "Foo", "Bar" }, target.SelectedItems);
  155. Assert.Equal(new[] { 3, 4 }, SelectedContainers(target));
  156. }
  157. }
  158. [Fact]
  159. public void Should_Shift_Select_Correct_Item_When_Duplicates_Are_Present()
  160. {
  161. using (UnitTestApplication.Start())
  162. {
  163. var target = new ListBox
  164. {
  165. Template = new FuncControlTemplate(CreateListBoxTemplate),
  166. ItemsSource = new[] { "Foo", "Bar", "Baz", "Foo", "Bar", "Baz" },
  167. SelectionMode = SelectionMode.Multiple,
  168. Width = 100,
  169. Height = 100,
  170. };
  171. var root = new TestRoot(target);
  172. root.LayoutManager.ExecuteInitialLayoutPass();
  173. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  174. _helper.Click(target.Presenter.Panel.Children[3]);
  175. _helper.Click(target.Presenter.Panel.Children[5], modifiers: KeyModifiers.Shift);
  176. var panel = target.Presenter.Panel;
  177. Assert.Equal(new[] { "Foo", "Bar", "Baz" }, target.SelectedItems);
  178. Assert.Equal(new[] { 3, 4, 5 }, SelectedContainers(target));
  179. }
  180. }
  181. [Fact]
  182. public void Can_Shift_Select_All_Items_When_Duplicates_Are_Present()
  183. {
  184. using (UnitTestApplication.Start())
  185. {
  186. var target = new ListBox
  187. {
  188. Template = new FuncControlTemplate(CreateListBoxTemplate),
  189. ItemsSource = new[] { "Foo", "Bar", "Baz", "Foo", "Bar", "Baz" },
  190. SelectionMode = SelectionMode.Multiple,
  191. Width = 100,
  192. Height = 100,
  193. };
  194. var root = new TestRoot(target);
  195. root.LayoutManager.ExecuteInitialLayoutPass();
  196. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  197. _helper.Click(target.Presenter.Panel.Children[0]);
  198. _helper.Click(target.Presenter.Panel.Children[5], modifiers: KeyModifiers.Shift);
  199. var panel = target.Presenter.Panel;
  200. Assert.Equal(new[] { "Foo", "Bar", "Baz", "Foo", "Bar", "Baz" }, target.SelectedItems);
  201. Assert.Equal(new[] { 0, 1, 2, 3, 4, 5 }, SelectedContainers(target));
  202. }
  203. }
  204. [Fact]
  205. public void Shift_Selecting_Raises_SelectionChanged_Events()
  206. {
  207. using (UnitTestApplication.Start())
  208. {
  209. var target = new ListBox
  210. {
  211. Template = new FuncControlTemplate(CreateListBoxTemplate),
  212. ItemsSource = new[] { "Foo", "Bar", "Baz", "Qux" },
  213. SelectionMode = SelectionMode.Multiple,
  214. Width = 100,
  215. Height = 100,
  216. };
  217. var root = new TestRoot(target);
  218. root.LayoutManager.ExecuteInitialLayoutPass();
  219. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  220. SelectionChangedEventArgs receivedArgs = null;
  221. target.SelectionChanged += (_, args) => receivedArgs = args;
  222. void VerifyAdded(params string[] selection)
  223. {
  224. Assert.NotNull(receivedArgs);
  225. Assert.Equal(selection, receivedArgs.AddedItems);
  226. Assert.Empty(receivedArgs.RemovedItems);
  227. }
  228. void VerifyRemoved(string selection)
  229. {
  230. Assert.NotNull(receivedArgs);
  231. Assert.Equal(new[] { selection }, receivedArgs.RemovedItems);
  232. Assert.Empty(receivedArgs.AddedItems);
  233. }
  234. _helper.Click(target.Presenter.Panel.Children[1]);
  235. VerifyAdded("Bar");
  236. receivedArgs = null;
  237. _helper.Click(target.Presenter.Panel.Children[3], modifiers: KeyModifiers.Shift);
  238. VerifyAdded("Baz", "Qux");
  239. receivedArgs = null;
  240. _helper.Click(target.Presenter.Panel.Children[2], modifiers: KeyModifiers.Shift);
  241. VerifyRemoved("Qux");
  242. }
  243. }
  244. [Fact]
  245. public void Duplicate_Items_Are_Added_To_SelectedItems_In_Order()
  246. {
  247. using (UnitTestApplication.Start())
  248. {
  249. var target = new ListBox
  250. {
  251. Template = new FuncControlTemplate(CreateListBoxTemplate),
  252. ItemsSource = new[] { "Foo", "Bar", "Baz", "Foo", "Bar", "Baz" },
  253. SelectionMode = SelectionMode.Multiple,
  254. Width = 100,
  255. Height = 100,
  256. };
  257. var root = new TestRoot(target);
  258. root.LayoutManager.ExecuteInitialLayoutPass();
  259. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  260. _helper.Click(target.Presenter.Panel.Children[0]);
  261. Assert.Equal(new[] { "Foo" }, target.SelectedItems);
  262. _helper.Click(target.Presenter.Panel.Children[4], modifiers: KeyModifiers.Control);
  263. Assert.Equal(new[] { "Foo", "Bar" }, target.SelectedItems);
  264. _helper.Click(target.Presenter.Panel.Children[3], modifiers: KeyModifiers.Control);
  265. Assert.Equal(new[] { "Foo", "Bar", "Foo" }, target.SelectedItems);
  266. _helper.Click(target.Presenter.Panel.Children[1], modifiers: KeyModifiers.Control);
  267. Assert.Equal(new[] { "Foo", "Bar", "Foo", "Bar" }, target.SelectedItems);
  268. }
  269. }
  270. [Fact]
  271. public void Left_Click_On_SelectedItem_Should_Clear_Existing_Selection()
  272. {
  273. using (UnitTestApplication.Start())
  274. {
  275. var target = new ListBox
  276. {
  277. Template = new FuncControlTemplate(CreateListBoxTemplate),
  278. ItemsSource = new[] { "Foo", "Bar", "Baz" },
  279. ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
  280. SelectionMode = SelectionMode.Multiple,
  281. Width = 100,
  282. Height = 100,
  283. };
  284. var root = new TestRoot(target);
  285. root.LayoutManager.ExecuteInitialLayoutPass();
  286. target.SelectAll();
  287. Assert.Equal(3, target.SelectedItems.Count);
  288. _helper.Click(target.Presenter.Panel.Children[0]);
  289. Assert.Equal(1, target.SelectedItems.Count);
  290. Assert.Equal(new[] { "Foo", }, target.SelectedItems);
  291. Assert.Equal(new[] { 0 }, SelectedContainers(target));
  292. }
  293. }
  294. [Fact]
  295. public void Right_Click_On_SelectedItem_Should_Not_Clear_Existing_Selection()
  296. {
  297. using (UnitTestApplication.Start())
  298. {
  299. var target = new ListBox
  300. {
  301. Template = new FuncControlTemplate(CreateListBoxTemplate),
  302. ItemsSource = new[] { "Foo", "Bar", "Baz" },
  303. ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
  304. SelectionMode = SelectionMode.Multiple,
  305. Width = 100,
  306. Height = 100,
  307. };
  308. var root = new TestRoot(target);
  309. root.LayoutManager.ExecuteInitialLayoutPass();
  310. target.SelectAll();
  311. Assert.Equal(3, target.SelectedItems.Count);
  312. _helper.Click(target.Presenter.Panel.Children[0], MouseButton.Right);
  313. Assert.Equal(3, target.SelectedItems.Count);
  314. }
  315. }
  316. [Fact]
  317. public void Right_Click_On_UnselectedItem_Should_Clear_Existing_Selection()
  318. {
  319. using (UnitTestApplication.Start())
  320. {
  321. var target = new ListBox
  322. {
  323. Template = new FuncControlTemplate(CreateListBoxTemplate),
  324. ItemsSource = new[] { "Foo", "Bar", "Baz" },
  325. ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
  326. SelectionMode = SelectionMode.Multiple,
  327. Width = 100,
  328. Height = 100,
  329. };
  330. var root = new TestRoot(target);
  331. root.LayoutManager.ExecuteInitialLayoutPass();
  332. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  333. _helper.Click(target.Presenter.Panel.Children[0]);
  334. _helper.Click(target.Presenter.Panel.Children[1], modifiers: KeyModifiers.Shift);
  335. Assert.Equal(2, target.SelectedItems.Count);
  336. _helper.Click(target.Presenter.Panel.Children[2], MouseButton.Right);
  337. Assert.Equal(1, target.SelectedItems.Count);
  338. }
  339. }
  340. [Fact]
  341. public void Shift_Right_Click_Should_Not_Select_Multiple()
  342. {
  343. using (UnitTestApplication.Start())
  344. {
  345. var target = new ListBox
  346. {
  347. Template = new FuncControlTemplate(CreateListBoxTemplate),
  348. ItemsSource = new[] { "Foo", "Bar", "Baz" },
  349. ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
  350. SelectionMode = SelectionMode.Multiple,
  351. Width = 100,
  352. Height = 100,
  353. };
  354. var root = new TestRoot(target);
  355. root.LayoutManager.ExecuteInitialLayoutPass();
  356. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  357. _helper.Click(target.Presenter.Panel.Children[0]);
  358. _helper.Click(target.Presenter.Panel.Children[2], MouseButton.Right, modifiers: KeyModifiers.Shift);
  359. Assert.Equal(1, target.SelectedItems.Count);
  360. }
  361. }
  362. [Fact]
  363. public void Ctrl_Right_Click_Should_Not_Select_Multiple()
  364. {
  365. using (UnitTestApplication.Start())
  366. {
  367. var target = new ListBox
  368. {
  369. Template = new FuncControlTemplate(CreateListBoxTemplate),
  370. ItemsSource = new[] { "Foo", "Bar", "Baz" },
  371. ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
  372. SelectionMode = SelectionMode.Multiple,
  373. Width = 100,
  374. Height = 100,
  375. };
  376. var root = new TestRoot(target);
  377. root.LayoutManager.ExecuteInitialLayoutPass();
  378. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  379. _helper.Click(target.Presenter.Panel.Children[0]);
  380. _helper.Click(target.Presenter.Panel.Children[2], MouseButton.Right, modifiers: KeyModifiers.Control);
  381. Assert.Equal(1, target.SelectedItems.Count);
  382. }
  383. }
  384. [Fact]
  385. public void Shift_Arrow_Key_Selects_Range()
  386. {
  387. using var app = UnitTestApplication.Start(TestServices.RealFocus);
  388. var target = new ListBox
  389. {
  390. Template = new FuncControlTemplate(CreateListBoxTemplate),
  391. ItemsSource = new[] { "Foo", "Bar", "Baz" },
  392. SelectionMode = SelectionMode.Multiple,
  393. Width = 100,
  394. Height = 100,
  395. SelectedIndex = 0,
  396. };
  397. var root = new TestRoot(target);
  398. root.LayoutManager.ExecuteInitialLayoutPass();
  399. RaiseKeyEvent(target, Key.Down, KeyModifiers.Shift);
  400. Assert.Equal(new[] { "Foo", "Bar", }, target.SelectedItems);
  401. Assert.Equal(new[] { 0, 1 }, SelectedContainers(target));
  402. Assert.True(target.ContainerFromIndex(1).IsFocused);
  403. RaiseKeyEvent(target, Key.Down, KeyModifiers.Shift);
  404. Assert.Equal(new[] { "Foo", "Bar", "Baz", }, target.SelectedItems);
  405. Assert.Equal(new[] { 0, 1, 2 }, SelectedContainers(target));
  406. Assert.True(target.ContainerFromIndex(2).IsFocused);
  407. RaiseKeyEvent(target, Key.Up, KeyModifiers.Shift);
  408. Assert.Equal(new[] { "Foo", "Bar", }, target.SelectedItems);
  409. Assert.Equal(new[] { 0, 1 }, SelectedContainers(target));
  410. Assert.True(target.ContainerFromIndex(1).IsFocused);
  411. }
  412. [Fact]
  413. public void Shift_Down_Key_Selecting_Selects_Range_End_From_Focus()
  414. {
  415. using var app = UnitTestApplication.Start(TestServices.RealFocus);
  416. var target = new ListBox
  417. {
  418. Template = new FuncControlTemplate(CreateListBoxTemplate),
  419. ItemsSource = new[] { "Foo", "Bar", "Baz" },
  420. SelectionMode = SelectionMode.Multiple,
  421. Width = 100,
  422. Height = 100,
  423. SelectedIndex = 0,
  424. };
  425. var root = new TestRoot(target);
  426. root.LayoutManager.ExecuteInitialLayoutPass();
  427. target.ContainerFromIndex(1)!.Focus();
  428. RaiseKeyEvent(target, Key.Down, KeyModifiers.Shift);
  429. Assert.Equal(new[] { "Foo", "Bar", "Baz" }, target.SelectedItems);
  430. Assert.Equal(new[] { 0, 1, 2 }, SelectedContainers(target));
  431. Assert.True(target.ContainerFromIndex(2).IsFocused);
  432. }
  433. [Fact]
  434. public void Shift_Down_Key_Selecting_Selects_Range_End_From_Focus_Moved_With_Ctrl_Key()
  435. {
  436. using var app = UnitTestApplication.Start(TestServices.RealFocus);
  437. var target = new ListBox
  438. {
  439. Template = new FuncControlTemplate(CreateListBoxTemplate),
  440. ItemsSource = new[] { "Foo", "Bar", "Baz", "Qux" },
  441. SelectionMode = SelectionMode.Multiple,
  442. Width = 100,
  443. Height = 100,
  444. SelectedIndex = 0,
  445. };
  446. var root = new TestRoot(target);
  447. root.LayoutManager.ExecuteInitialLayoutPass();
  448. RaiseKeyEvent(target, Key.Down, KeyModifiers.Shift);
  449. Assert.Equal(new[] { "Foo", "Bar" }, target.SelectedItems);
  450. Assert.Equal(new[] { 0, 1 }, SelectedContainers(target));
  451. Assert.True(target.ContainerFromIndex(1).IsFocused);
  452. RaiseKeyEvent(target, Key.Down, KeyModifiers.Control);
  453. Assert.Equal(new[] { "Foo", "Bar" }, target.SelectedItems);
  454. Assert.Equal(new[] { 0, 1 }, SelectedContainers(target));
  455. Assert.True(target.ContainerFromIndex(2).IsFocused);
  456. RaiseKeyEvent(target, Key.Down, KeyModifiers.Shift);
  457. Assert.Equal(new[] { "Foo", "Bar", "Baz", "Qux" }, target.SelectedItems);
  458. Assert.Equal(new[] { 0, 1, 2, 3 }, SelectedContainers(target));
  459. Assert.True(target.ContainerFromIndex(3).IsFocused);
  460. }
  461. private Control CreateListBoxTemplate(TemplatedControl parent, INameScope scope)
  462. {
  463. return new ScrollViewer
  464. {
  465. Template = new FuncControlTemplate(CreateScrollViewerTemplate),
  466. Content = new ItemsPresenter
  467. {
  468. Name = "PART_ItemsPresenter",
  469. }.RegisterInNameScope(scope)
  470. };
  471. }
  472. private Control CreateScrollViewerTemplate(TemplatedControl parent, INameScope scope)
  473. {
  474. return new ScrollContentPresenter
  475. {
  476. Name = "PART_ContentPresenter",
  477. [~ContentPresenter.ContentProperty] =
  478. ((Control)parent).GetObservable(ContentControl.ContentProperty).ToBinding(),
  479. }.RegisterInNameScope(scope);
  480. }
  481. private static void RaiseKeyEvent(Control target, Key key, KeyModifiers inputModifiers = 0)
  482. {
  483. target.RaiseEvent(new KeyEventArgs
  484. {
  485. RoutedEvent = InputElement.KeyDownEvent,
  486. KeyModifiers = inputModifiers,
  487. Key = key
  488. });
  489. }
  490. private static IEnumerable<int> SelectedContainers(SelectingItemsControl target)
  491. {
  492. return target.Presenter.Panel.Children
  493. .Select(x => x.Classes.Contains(":selected") ? target.IndexFromContainer(x) : -1)
  494. .Where(x => x != -1);
  495. }
  496. }
  497. }