SelectingItemsControlTests.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. // Copyright (c) The Avalonia 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.Collections.ObjectModel;
  5. using System.Collections.Specialized;
  6. using System.ComponentModel;
  7. using System.Linq;
  8. using Avalonia.Collections;
  9. using Avalonia.Controls.Presenters;
  10. using Avalonia.Controls.Primitives;
  11. using Avalonia.Controls.Templates;
  12. using Avalonia.Data;
  13. using Avalonia.Input;
  14. using Avalonia.Interactivity;
  15. using Avalonia.Markup.Data;
  16. using Avalonia.UnitTests;
  17. using Moq;
  18. using Xunit;
  19. namespace Avalonia.Controls.UnitTests.Primitives
  20. {
  21. public class SelectingItemsControlTests
  22. {
  23. private MouseTestHelper _helper = new MouseTestHelper();
  24. [Fact]
  25. public void SelectedIndex_Should_Initially_Be_Minus_1()
  26. {
  27. var items = new[]
  28. {
  29. new Item(),
  30. new Item(),
  31. };
  32. var target = new SelectingItemsControl
  33. {
  34. Items = items,
  35. Template = Template(),
  36. };
  37. Assert.Equal(-1, target.SelectedIndex);
  38. }
  39. [Fact]
  40. public void Item_IsSelected_Should_Initially_Be_False()
  41. {
  42. var items = new[]
  43. {
  44. new Item(),
  45. new Item(),
  46. };
  47. var target = new SelectingItemsControl
  48. {
  49. Items = items,
  50. Template = Template(),
  51. };
  52. target.ApplyTemplate();
  53. Assert.False(items[0].IsSelected);
  54. Assert.False(items[1].IsSelected);
  55. }
  56. [Fact]
  57. public void Setting_SelectedItem_Should_Set_Item_IsSelected_True()
  58. {
  59. var items = new[]
  60. {
  61. new Item(),
  62. new Item(),
  63. };
  64. var target = new SelectingItemsControl
  65. {
  66. Items = items,
  67. Template = Template(),
  68. };
  69. target.ApplyTemplate();
  70. target.Presenter.ApplyTemplate();
  71. target.SelectedItem = items[1];
  72. Assert.False(items[0].IsSelected);
  73. Assert.True(items[1].IsSelected);
  74. }
  75. [Fact]
  76. public void Setting_SelectedItem_Before_ApplyTemplate_Should_Set_Item_IsSelected_True()
  77. {
  78. var items = new[]
  79. {
  80. new Item(),
  81. new Item(),
  82. };
  83. var target = new SelectingItemsControl
  84. {
  85. Items = items,
  86. Template = Template(),
  87. };
  88. target.SelectedItem = items[1];
  89. target.ApplyTemplate();
  90. target.Presenter.ApplyTemplate();
  91. Assert.False(items[0].IsSelected);
  92. Assert.True(items[1].IsSelected);
  93. }
  94. [Fact]
  95. public void Setting_SelectedIndex_During_Initialize_Should_Select_Item_When_AlwaysSelected_Is_Used()
  96. {
  97. var listBox = new ListBox
  98. {
  99. SelectionMode = SelectionMode.Single | SelectionMode.AlwaysSelected
  100. };
  101. listBox.BeginInit();
  102. listBox.SelectedIndex = 1;
  103. var items = new AvaloniaList<string>();
  104. listBox.Items = items;
  105. items.Add("A");
  106. items.Add("B");
  107. items.Add("C");
  108. listBox.EndInit();
  109. Assert.Equal("B", listBox.SelectedItem);
  110. }
  111. [Fact]
  112. public void Setting_SelectedIndex_Before_ApplyTemplate_Should_Set_Item_IsSelected_True()
  113. {
  114. var items = new[]
  115. {
  116. new Item(),
  117. new Item(),
  118. };
  119. var target = new SelectingItemsControl
  120. {
  121. Items = items,
  122. Template = Template(),
  123. };
  124. target.SelectedIndex = 1;
  125. target.ApplyTemplate();
  126. target.Presenter.ApplyTemplate();
  127. Assert.False(items[0].IsSelected);
  128. Assert.True(items[1].IsSelected);
  129. }
  130. [Fact]
  131. public void Setting_SelectedItem_Should_Set_SelectedIndex()
  132. {
  133. var items = new[]
  134. {
  135. new Item(),
  136. new Item(),
  137. };
  138. var target = new SelectingItemsControl
  139. {
  140. Items = items,
  141. Template = Template(),
  142. };
  143. target.ApplyTemplate();
  144. target.SelectedItem = items[1];
  145. Assert.Equal(items[1], target.SelectedItem);
  146. Assert.Equal(1, target.SelectedIndex);
  147. }
  148. [Fact]
  149. public void SelectedIndex_Item_Is_Updated_As_Items_Removed_When_Last_Item_Is_Selected()
  150. {
  151. var items = new ObservableCollection<string>
  152. {
  153. "Foo",
  154. "Bar",
  155. "FooBar"
  156. };
  157. var target = new SelectingItemsControl
  158. {
  159. Items = items,
  160. Template = Template(),
  161. };
  162. target.ApplyTemplate();
  163. target.SelectedItem = items[2];
  164. Assert.Equal(items[2], target.SelectedItem);
  165. Assert.Equal(2, target.SelectedIndex);
  166. items.RemoveAt(0);
  167. Assert.Equal(items[1], target.SelectedItem);
  168. Assert.Equal(1, target.SelectedIndex);
  169. }
  170. [Fact]
  171. public void Setting_SelectedItem_To_Not_Present_Item_Should_Clear_Selection()
  172. {
  173. var items = new[]
  174. {
  175. new Item(),
  176. new Item(),
  177. };
  178. var target = new SelectingItemsControl
  179. {
  180. Items = items,
  181. Template = Template(),
  182. };
  183. target.ApplyTemplate();
  184. target.SelectedItem = items[1];
  185. Assert.Equal(items[1], target.SelectedItem);
  186. Assert.Equal(1, target.SelectedIndex);
  187. target.SelectedItem = new Item();
  188. Assert.Null(target.SelectedItem);
  189. Assert.Equal(-1, target.SelectedIndex);
  190. }
  191. [Fact]
  192. public void Setting_SelectedIndex_Should_Set_SelectedItem()
  193. {
  194. var items = new[]
  195. {
  196. new Item(),
  197. new Item(),
  198. };
  199. var target = new SelectingItemsControl
  200. {
  201. Items = items,
  202. Template = Template(),
  203. };
  204. target.ApplyTemplate();
  205. target.SelectedIndex = 1;
  206. Assert.Equal(items[1], target.SelectedItem);
  207. }
  208. [Fact]
  209. public void Setting_SelectedIndex_Out_Of_Bounds_Should_Clear_Selection()
  210. {
  211. var items = new[]
  212. {
  213. new Item(),
  214. new Item(),
  215. };
  216. var target = new SelectingItemsControl
  217. {
  218. Items = items,
  219. Template = Template(),
  220. };
  221. target.ApplyTemplate();
  222. target.SelectedIndex = 2;
  223. Assert.Equal(-1, target.SelectedIndex);
  224. }
  225. [Fact]
  226. public void Setting_SelectedItem_To_Non_Existent_Item_Should_Clear_Selection()
  227. {
  228. var target = new SelectingItemsControl
  229. {
  230. Template = Template(),
  231. };
  232. target.ApplyTemplate();
  233. target.SelectedItem = new Item();
  234. Assert.Equal(-1, target.SelectedIndex);
  235. Assert.Null(target.SelectedItem);
  236. }
  237. [Fact]
  238. public void Adding_Selected_Item_Should_Update_Selection()
  239. {
  240. var items = new AvaloniaList<Item>(new[]
  241. {
  242. new Item(),
  243. new Item(),
  244. });
  245. var target = new SelectingItemsControl
  246. {
  247. Items = items,
  248. Template = Template(),
  249. };
  250. target.ApplyTemplate();
  251. target.Presenter.ApplyTemplate();
  252. items.Add(new Item { IsSelected = true });
  253. Assert.Equal(2, target.SelectedIndex);
  254. Assert.Equal(items[2], target.SelectedItem);
  255. }
  256. [Fact]
  257. public void Setting_Items_To_Null_Should_Clear_Selection()
  258. {
  259. var items = new AvaloniaList<Item>
  260. {
  261. new Item(),
  262. new Item(),
  263. };
  264. var target = new SelectingItemsControl
  265. {
  266. Items = items,
  267. Template = Template(),
  268. };
  269. target.ApplyTemplate();
  270. target.SelectedIndex = 1;
  271. Assert.Equal(items[1], target.SelectedItem);
  272. Assert.Equal(1, target.SelectedIndex);
  273. target.Items = null;
  274. Assert.Null(target.SelectedItem);
  275. Assert.Equal(-1, target.SelectedIndex);
  276. }
  277. [Fact]
  278. public void Removing_Selected_Item_Should_Clear_Selection()
  279. {
  280. var items = new AvaloniaList<Item>
  281. {
  282. new Item(),
  283. new Item(),
  284. };
  285. var target = new SelectingItemsControl
  286. {
  287. Items = items,
  288. Template = Template(),
  289. };
  290. target.ApplyTemplate();
  291. target.SelectedIndex = 1;
  292. Assert.Equal(items[1], target.SelectedItem);
  293. Assert.Equal(1, target.SelectedIndex);
  294. items.RemoveAt(1);
  295. Assert.Null(target.SelectedItem);
  296. Assert.Equal(-1, target.SelectedIndex);
  297. }
  298. [Fact]
  299. public void Moving_Selected_Item_Should_Update_Selection()
  300. {
  301. var items = new AvaloniaList<Item>
  302. {
  303. new Item(),
  304. new Item(),
  305. };
  306. var target = new SelectingItemsControl
  307. {
  308. Items = items,
  309. Template = Template(),
  310. };
  311. target.ApplyTemplate();
  312. target.SelectedIndex = 0;
  313. Assert.Equal(items[0], target.SelectedItem);
  314. Assert.Equal(0, target.SelectedIndex);
  315. items.Move(0, 1);
  316. Assert.Equal(items[1], target.SelectedItem);
  317. Assert.Equal(1, target.SelectedIndex);
  318. }
  319. [Fact]
  320. public void Resetting_Items_Collection_Should_Clear_Selection()
  321. {
  322. // Need to use ObservableCollection here as AvaloniaList signals a Clear as an
  323. // add + remove.
  324. var items = new ObservableCollection<Item>
  325. {
  326. new Item(),
  327. new Item(),
  328. };
  329. var target = new SelectingItemsControl
  330. {
  331. Items = items,
  332. Template = Template(),
  333. };
  334. target.ApplyTemplate();
  335. target.SelectedIndex = 1;
  336. Assert.Equal(items[1], target.SelectedItem);
  337. Assert.Equal(1, target.SelectedIndex);
  338. items.Clear();
  339. Assert.Null(target.SelectedItem);
  340. Assert.Equal(-1, target.SelectedIndex);
  341. }
  342. [Fact]
  343. public void Raising_IsSelectedChanged_On_Item_Should_Update_Selection()
  344. {
  345. var items = new[]
  346. {
  347. new Item(),
  348. new Item(),
  349. };
  350. var target = new SelectingItemsControl
  351. {
  352. Items = items,
  353. Template = Template(),
  354. };
  355. target.ApplyTemplate();
  356. target.Presenter.ApplyTemplate();
  357. target.SelectedItem = items[1];
  358. Assert.False(items[0].IsSelected);
  359. Assert.True(items[1].IsSelected);
  360. items[0].IsSelected = true;
  361. items[0].RaiseEvent(new RoutedEventArgs(SelectingItemsControl.IsSelectedChangedEvent));
  362. Assert.Equal(0, target.SelectedIndex);
  363. Assert.Equal(items[0], target.SelectedItem);
  364. Assert.True(items[0].IsSelected);
  365. Assert.False(items[1].IsSelected);
  366. }
  367. [Fact]
  368. public void Clearing_IsSelected_And_Raising_IsSelectedChanged_On_Item_Should_Update_Selection()
  369. {
  370. var items = new[]
  371. {
  372. new Item(),
  373. new Item(),
  374. };
  375. var target = new SelectingItemsControl
  376. {
  377. Items = items,
  378. Template = Template(),
  379. };
  380. target.ApplyTemplate();
  381. target.Presenter.ApplyTemplate();
  382. target.SelectedItem = items[1];
  383. Assert.False(items[0].IsSelected);
  384. Assert.True(items[1].IsSelected);
  385. items[1].IsSelected = false;
  386. items[1].RaiseEvent(new RoutedEventArgs(SelectingItemsControl.IsSelectedChangedEvent));
  387. Assert.Equal(-1, target.SelectedIndex);
  388. Assert.Null(target.SelectedItem);
  389. }
  390. [Fact]
  391. public void Raising_IsSelectedChanged_On_Someone_Elses_Item_Should_Not_Update_Selection()
  392. {
  393. var items = new[]
  394. {
  395. new Item(),
  396. new Item(),
  397. };
  398. var target = new SelectingItemsControl
  399. {
  400. Items = items,
  401. Template = Template(),
  402. };
  403. target.ApplyTemplate();
  404. target.SelectedItem = items[1];
  405. var notChild = new Item
  406. {
  407. IsSelected = true,
  408. };
  409. target.RaiseEvent(new RoutedEventArgs
  410. {
  411. RoutedEvent = SelectingItemsControl.IsSelectedChangedEvent,
  412. Source = notChild,
  413. });
  414. Assert.Equal(target.SelectedItem, items[1]);
  415. }
  416. [Fact]
  417. public void Setting_SelectedIndex_Should_Raise_SelectionChanged_Event()
  418. {
  419. var items = new[]
  420. {
  421. new Item(),
  422. new Item(),
  423. };
  424. var target = new SelectingItemsControl
  425. {
  426. Items = items,
  427. Template = Template(),
  428. };
  429. var called = false;
  430. target.SelectionChanged += (s, e) =>
  431. {
  432. Assert.Same(items[1], e.AddedItems.Cast<object>().Single());
  433. Assert.Empty(e.RemovedItems);
  434. called = true;
  435. };
  436. target.SelectedIndex = 1;
  437. Assert.True(called);
  438. }
  439. [Fact]
  440. public void Clearing_SelectedIndex_Should_Raise_SelectionChanged_Event()
  441. {
  442. var items = new[]
  443. {
  444. new Item(),
  445. new Item(),
  446. };
  447. var target = new SelectingItemsControl
  448. {
  449. Items = items,
  450. Template = Template(),
  451. SelectedIndex = 1,
  452. };
  453. target.ApplyTemplate();
  454. target.Presenter.ApplyTemplate();
  455. var called = false;
  456. target.SelectionChanged += (s, e) =>
  457. {
  458. Assert.Same(items[1], e.RemovedItems.Cast<object>().Single());
  459. Assert.Empty(e.AddedItems);
  460. called = true;
  461. };
  462. target.SelectedIndex = -1;
  463. Assert.True(called);
  464. }
  465. [Fact]
  466. public void Order_Of_Setting_Items_And_SelectedIndex_During_Initialization_Should_Not_Matter()
  467. {
  468. var items = new[] { "Foo", "Bar" };
  469. var target = new SelectingItemsControl();
  470. ((ISupportInitialize)target).BeginInit();
  471. target.SelectedIndex = 1;
  472. target.Items = items;
  473. ((ISupportInitialize)target).EndInit();
  474. Assert.Equal(1, target.SelectedIndex);
  475. Assert.Equal("Bar", target.SelectedItem);
  476. }
  477. [Fact]
  478. public void Order_Of_Setting_Items_And_SelectedItem_During_Initialization_Should_Not_Matter()
  479. {
  480. var items = new[] { "Foo", "Bar" };
  481. var target = new SelectingItemsControl();
  482. ((ISupportInitialize)target).BeginInit();
  483. target.SelectedItem = "Bar";
  484. target.Items = items;
  485. ((ISupportInitialize)target).EndInit();
  486. Assert.Equal(1, target.SelectedIndex);
  487. Assert.Equal("Bar", target.SelectedItem);
  488. }
  489. [Fact]
  490. public void Changing_DataContext_Should_Not_Clear_Nested_ViewModel_SelectedItem()
  491. {
  492. var items = new[]
  493. {
  494. new Item(),
  495. new Item(),
  496. };
  497. var vm = new MasterViewModel
  498. {
  499. Child = new ChildViewModel
  500. {
  501. Items = items,
  502. SelectedItem = items[1],
  503. }
  504. };
  505. var target = new SelectingItemsControl { DataContext = vm };
  506. var itemsBinding = new Binding("Child.Items");
  507. var selectedBinding = new Binding("Child.SelectedItem");
  508. target.Bind(SelectingItemsControl.ItemsProperty, itemsBinding);
  509. target.Bind(SelectingItemsControl.SelectedItemProperty, selectedBinding);
  510. Assert.Equal(1, target.SelectedIndex);
  511. Assert.Same(vm.Child.SelectedItem, target.SelectedItem);
  512. items = new[]
  513. {
  514. new Item { Value = "Item1" },
  515. new Item { Value = "Item2" },
  516. new Item { Value = "Item3" },
  517. };
  518. vm = new MasterViewModel
  519. {
  520. Child = new ChildViewModel
  521. {
  522. Items = items,
  523. SelectedItem = items[2],
  524. }
  525. };
  526. target.DataContext = vm;
  527. Assert.Equal(2, target.SelectedIndex);
  528. Assert.Same(vm.Child.SelectedItem, target.SelectedItem);
  529. }
  530. [Fact]
  531. public void Nested_ListBox_Does_Not_Change_Parent_SelectedIndex()
  532. {
  533. SelectingItemsControl nested;
  534. var root = new SelectingItemsControl
  535. {
  536. Template = Template(),
  537. Items = new IControl[]
  538. {
  539. new Border(),
  540. nested = new ListBox
  541. {
  542. Template = Template(),
  543. Items = new[] { "foo", "bar" },
  544. SelectedIndex = 1,
  545. }
  546. },
  547. SelectedIndex = 0,
  548. };
  549. root.ApplyTemplate();
  550. root.Presenter.ApplyTemplate();
  551. nested.ApplyTemplate();
  552. nested.Presenter.ApplyTemplate();
  553. Assert.Equal(0, root.SelectedIndex);
  554. Assert.Equal(1, nested.SelectedIndex);
  555. nested.SelectedIndex = 0;
  556. Assert.Equal(0, root.SelectedIndex);
  557. }
  558. [Fact]
  559. public void Setting_SelectedItem_With_Pointer_Should_Set_TabOnceActiveElement()
  560. {
  561. var target = new ListBox
  562. {
  563. Template = Template(),
  564. Items = new[] { "Foo", "Bar", "Baz " },
  565. };
  566. target.ApplyTemplate();
  567. target.Presenter.ApplyTemplate();
  568. _helper.Down((Interactive)target.Presenter.Panel.Children[1]);
  569. var panel = target.Presenter.Panel;
  570. Assert.Equal(
  571. KeyboardNavigation.GetTabOnceActiveElement((InputElement)panel),
  572. panel.Children[1]);
  573. }
  574. [Fact]
  575. public void Removing_SelectedItem_Should_Clear_TabOnceActiveElement()
  576. {
  577. var items = new ObservableCollection<string>(new[] { "Foo", "Bar", "Baz " });
  578. var target = new ListBox
  579. {
  580. Template = Template(),
  581. Items = items,
  582. };
  583. target.ApplyTemplate();
  584. target.Presenter.ApplyTemplate();
  585. _helper.Down(target.Presenter.Panel.Children[1]);
  586. items.RemoveAt(1);
  587. var panel = target.Presenter.Panel;
  588. Assert.Null(KeyboardNavigation.GetTabOnceActiveElement((InputElement)panel));
  589. }
  590. [Fact]
  591. public void Resetting_Items_Collection_Should_Retain_Selection()
  592. {
  593. var itemsMock = new Mock<List<string>>();
  594. var itemsMockAsINCC = itemsMock.As<INotifyCollectionChanged>();
  595. itemsMock.Object.AddRange(new[] { "Foo", "Bar", "Baz" });
  596. var target = new SelectingItemsControl
  597. {
  598. Items = itemsMock.Object
  599. };
  600. target.SelectedIndex = 1;
  601. itemsMockAsINCC.Raise(e => e.CollectionChanged += null, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
  602. Assert.True(target.SelectedIndex == 1);
  603. }
  604. [Fact]
  605. public void Binding_With_DelayedBinding_And_Initialization_Where_DataContext_Is_Root_Works()
  606. {
  607. // Test for #1932.
  608. var root = new RootWithItems();
  609. root.BeginInit();
  610. root.DataContext = root;
  611. var target = new ListBox();
  612. target.BeginInit();
  613. root.Child = target;
  614. DelayedBinding.Add(target, ItemsControl.ItemsProperty, new Binding(nameof(RootWithItems.Items)));
  615. DelayedBinding.Add(target, ListBox.SelectedItemProperty, new Binding(nameof(RootWithItems.Selected)));
  616. target.EndInit();
  617. root.EndInit();
  618. Assert.Equal("b", target.SelectedItem);
  619. }
  620. [Fact]
  621. public void Mode_For_SelectedIndex_Is_TwoWay_By_Default()
  622. {
  623. var items = new[]
  624. {
  625. new Item(),
  626. new Item(),
  627. new Item(),
  628. };
  629. var vm = new MasterViewModel
  630. {
  631. Child = new ChildViewModel
  632. {
  633. Items = items,
  634. SelectedIndex = 1,
  635. }
  636. };
  637. var target = new SelectingItemsControl { DataContext = vm };
  638. var itemsBinding = new Binding("Child.Items");
  639. var selectedIndBinding = new Binding("Child.SelectedIndex");
  640. target.Bind(SelectingItemsControl.ItemsProperty, itemsBinding);
  641. target.Bind(SelectingItemsControl.SelectedIndexProperty, selectedIndBinding);
  642. Assert.Equal(1, target.SelectedIndex);
  643. target.SelectedIndex = 2;
  644. Assert.Equal(2, target.SelectedIndex);
  645. Assert.Equal(2, vm.Child.SelectedIndex);
  646. }
  647. [Fact]
  648. public void Should_Select_Correct_Item_When_Duplicate_Items_Are_Present()
  649. {
  650. var target = new ListBox
  651. {
  652. Template = Template(),
  653. Items = new[] { "Foo", "Bar", "Baz", "Foo", "Bar", "Baz"},
  654. };
  655. target.ApplyTemplate();
  656. target.Presenter.ApplyTemplate();
  657. _helper.Down((Interactive)target.Presenter.Panel.Children[3]);
  658. Assert.Equal(3, target.SelectedIndex);
  659. }
  660. [Fact]
  661. public void Should_Apply_Selected_Pseudoclass_To_Correct_Item_When_Duplicate_Items_Are_Present()
  662. {
  663. var target = new ListBox
  664. {
  665. Template = Template(),
  666. Items = new[] { "Foo", "Bar", "Baz", "Foo", "Bar", "Baz" },
  667. };
  668. target.ApplyTemplate();
  669. target.Presenter.ApplyTemplate();
  670. _helper.Down((Interactive)target.Presenter.Panel.Children[3]);
  671. Assert.Equal(new[] { ":selected" }, target.Presenter.Panel.Children[3].Classes);
  672. }
  673. [Fact]
  674. public void Adding_Item_Before_SelectedItem_Should_Update_SelectedIndex()
  675. {
  676. var items = new ObservableCollection<string>
  677. {
  678. "Foo",
  679. "Bar",
  680. "Baz"
  681. };
  682. var target = new ListBox
  683. {
  684. Template = Template(),
  685. Items = items,
  686. SelectedIndex = 1,
  687. };
  688. target.ApplyTemplate();
  689. target.Presenter.ApplyTemplate();
  690. items.Insert(0, "Qux");
  691. Assert.Equal(2, target.SelectedIndex);
  692. Assert.Equal("Bar", target.SelectedItem);
  693. }
  694. [Fact]
  695. public void Removing_Item_Before_SelectedItem_Should_Update_SelectedIndex()
  696. {
  697. var items = new ObservableCollection<string>
  698. {
  699. "Foo",
  700. "Bar",
  701. "Baz"
  702. };
  703. var target = new ListBox
  704. {
  705. Template = Template(),
  706. Items = items,
  707. SelectedIndex = 1,
  708. };
  709. target.ApplyTemplate();
  710. target.Presenter.ApplyTemplate();
  711. items.RemoveAt(0);
  712. Assert.Equal(0, target.SelectedIndex);
  713. Assert.Equal("Bar", target.SelectedItem);
  714. }
  715. [Fact]
  716. public void Replacing_Selected_Item_Should_Update_SelectedItem()
  717. {
  718. var items = new ObservableCollection<string>
  719. {
  720. "Foo",
  721. "Bar",
  722. "Baz"
  723. };
  724. var target = new ListBox
  725. {
  726. Template = Template(),
  727. Items = items,
  728. SelectedIndex = 1,
  729. };
  730. target.ApplyTemplate();
  731. target.Presenter.ApplyTemplate();
  732. items[1] = "Qux";
  733. Assert.Equal(1, target.SelectedIndex);
  734. Assert.Equal("Qux", target.SelectedItem);
  735. }
  736. [Fact]
  737. public void AutoScrollToSelectedItem_Causes_Scroll_To_SelectedItem()
  738. {
  739. var items = new ObservableCollection<string>
  740. {
  741. "Foo",
  742. "Bar",
  743. "Baz"
  744. };
  745. var target = new ListBox
  746. {
  747. Template = Template(),
  748. Items = items,
  749. };
  750. target.ApplyTemplate();
  751. target.Presenter.ApplyTemplate();
  752. var raised = false;
  753. target.AddHandler(Control.RequestBringIntoViewEvent, (s, e) => raised = true);
  754. target.SelectedIndex = 2;
  755. Assert.True(raised);
  756. }
  757. [Fact]
  758. public void Can_Set_Both_SelectedItem_And_SelectedItems_During_Initialization()
  759. {
  760. // Issue #2969.
  761. var target = new ListBox();
  762. var selectedItems = new List<object>();
  763. target.BeginInit();
  764. target.Template = Template();
  765. target.Items = new[] { "Foo", "Bar", "Baz" };
  766. target.SelectedItems = selectedItems;
  767. target.SelectedItem = "Bar";
  768. target.EndInit();
  769. Assert.Equal("Bar", target.SelectedItem);
  770. Assert.Equal(1, target.SelectedIndex);
  771. Assert.Same(selectedItems, target.SelectedItems);
  772. Assert.Equal(new[] { "Bar" }, selectedItems);
  773. }
  774. private FuncControlTemplate Template()
  775. {
  776. return new FuncControlTemplate<SelectingItemsControl>((control, scope) =>
  777. new ItemsPresenter
  778. {
  779. Name = "itemsPresenter",
  780. [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty],
  781. [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty],
  782. }.RegisterInNameScope(scope));
  783. }
  784. private class Item : Control, ISelectable
  785. {
  786. public string Value { get; set; }
  787. public bool IsSelected { get; set; }
  788. }
  789. private class MasterViewModel : NotifyingBase
  790. {
  791. private ChildViewModel _child;
  792. public ChildViewModel Child
  793. {
  794. get { return _child; }
  795. set
  796. {
  797. _child = value;
  798. RaisePropertyChanged();
  799. }
  800. }
  801. }
  802. private class ChildViewModel : NotifyingBase
  803. {
  804. public IList<Item> Items { get; set; }
  805. public Item SelectedItem { get; set; }
  806. public int SelectedIndex { get; set; }
  807. }
  808. private class RootWithItems : TestRoot
  809. {
  810. public List<string> Items { get; set; } = new List<string>() { "a", "b", "c", "d", "e" };
  811. public string Selected { get; set; } = "b";
  812. }
  813. }
  814. }