ListBoxTests_Multiple.cs 28 KB

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