SelectingItemsControlTests.cs 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288
  1. using System;
  2. using System.Collections;
  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 System.Reactive.Disposables;
  9. using System.Threading.Tasks;
  10. using Avalonia.Collections;
  11. using Avalonia.Controls.Presenters;
  12. using Avalonia.Controls.Primitives;
  13. using Avalonia.Controls.Selection;
  14. using Avalonia.Controls.Templates;
  15. using Avalonia.Data;
  16. using Avalonia.Input;
  17. using Avalonia.Input.Platform;
  18. using Avalonia.Interactivity;
  19. using Avalonia.Layout;
  20. using Avalonia.Markup.Data;
  21. using Avalonia.Platform;
  22. using Avalonia.Styling;
  23. using Avalonia.Threading;
  24. using Avalonia.UnitTests;
  25. using Avalonia.VisualTree;
  26. using Moq;
  27. using Xunit;
  28. namespace Avalonia.Controls.UnitTests.Primitives
  29. {
  30. public partial class SelectingItemsControlTests
  31. {
  32. private MouseTestHelper _helper = new MouseTestHelper();
  33. [Fact]
  34. public void SelectedIndex_Should_Initially_Be_Minus_1()
  35. {
  36. var items = new[]
  37. {
  38. new Item(),
  39. new Item(),
  40. };
  41. var target = new SelectingItemsControl
  42. {
  43. ItemsSource = items,
  44. Template = Template(),
  45. };
  46. Assert.Equal(-1, target.SelectedIndex);
  47. }
  48. [Fact]
  49. public void Item_IsSelected_Should_Initially_Be_False()
  50. {
  51. var items = new[]
  52. {
  53. new Item(),
  54. new Item(),
  55. };
  56. var target = new SelectingItemsControl
  57. {
  58. ItemsSource = items,
  59. Template = Template(),
  60. };
  61. Prepare(target);
  62. Assert.False(items[0].IsSelected);
  63. Assert.False(items[1].IsSelected);
  64. }
  65. [Fact]
  66. public void Setting_SelectedItem_Should_Set_Item_IsSelected_True()
  67. {
  68. var items = new[]
  69. {
  70. new Item(),
  71. new Item(),
  72. };
  73. var target = new SelectingItemsControl
  74. {
  75. ItemsSource = items,
  76. Template = Template(),
  77. };
  78. Prepare(target);
  79. target.SelectedItem = items[1];
  80. Assert.False(items[0].IsSelected);
  81. Assert.True(items[1].IsSelected);
  82. }
  83. [Fact]
  84. public void Setting_SelectedItem_Before_ApplyTemplate_Should_Set_Item_IsSelected_True()
  85. {
  86. var items = new[]
  87. {
  88. new Item(),
  89. new Item(),
  90. };
  91. var target = new SelectingItemsControl
  92. {
  93. ItemsSource = items,
  94. Template = Template(),
  95. };
  96. target.SelectedItem = items[1];
  97. Prepare(target);
  98. Assert.False(items[0].IsSelected);
  99. Assert.True(items[1].IsSelected);
  100. }
  101. [Fact]
  102. public void SelectedIndex_Should_Be_Minus_1_After_Initialize()
  103. {
  104. var items = new[]
  105. {
  106. new Item(),
  107. new Item(),
  108. };
  109. var target = new ListBox();
  110. target.BeginInit();
  111. target.ItemsSource = items;
  112. target.Template = Template();
  113. target.EndInit();
  114. Assert.Equal(-1, target.SelectedIndex);
  115. }
  116. [Fact]
  117. public void SelectedIndex_Should_Be_Minus_1_Without_Initialize()
  118. {
  119. var items = new[]
  120. {
  121. new Item(),
  122. new Item(),
  123. };
  124. var target = new ListBox();
  125. target.ItemsSource = items;
  126. target.Template = Template();
  127. target.DataContext = new object();
  128. Assert.Equal(-1, target.SelectedIndex);
  129. }
  130. [Fact]
  131. public void SelectedIndex_Should_Be_0_After_Initialize_With_AlwaysSelected()
  132. {
  133. var items = new[]
  134. {
  135. new Item(),
  136. new Item(),
  137. };
  138. var target = new ListBox();
  139. target.BeginInit();
  140. target.SelectionMode = SelectionMode.Single | SelectionMode.AlwaysSelected;
  141. target.ItemsSource = items;
  142. target.Template = Template();
  143. target.EndInit();
  144. Prepare(target);
  145. Assert.Equal(0, target.SelectedIndex);
  146. }
  147. [Fact]
  148. public void Setting_SelectedIndex_During_Initialize_Should_Select_Item_When_AlwaysSelected_Is_Used()
  149. {
  150. var listBox = new ListBox
  151. {
  152. SelectionMode = SelectionMode.Single | SelectionMode.AlwaysSelected
  153. };
  154. listBox.BeginInit();
  155. listBox.SelectedIndex = 1;
  156. var items = new AvaloniaList<string>();
  157. listBox.ItemsSource = items;
  158. items.Add("A");
  159. items.Add("B");
  160. items.Add("C");
  161. listBox.EndInit();
  162. Prepare(listBox);
  163. Assert.Equal("B", listBox.SelectedItem);
  164. }
  165. [Fact]
  166. public void Setting_SelectedIndex_Before_Initialize_Should_Retain_Selection()
  167. {
  168. var listBox = new ListBox
  169. {
  170. SelectionMode = SelectionMode.Single,
  171. ItemsSource = new[] { "foo", "bar", "baz" },
  172. SelectedIndex = 1
  173. };
  174. listBox.BeginInit();
  175. listBox.EndInit();
  176. Assert.Equal(1, listBox.SelectedIndex);
  177. Assert.Equal("bar", listBox.SelectedItem);
  178. }
  179. [Fact]
  180. public void Setting_SelectedIndex_During_Initialize_Should_Take_Priority_Over_Previous_Value()
  181. {
  182. var listBox = new ListBox
  183. {
  184. SelectionMode = SelectionMode.Single,
  185. ItemsSource = new[] { "foo", "bar", "baz" },
  186. SelectedIndex = 2
  187. };
  188. listBox.BeginInit();
  189. listBox.SelectedIndex = 1;
  190. listBox.EndInit();
  191. Assert.Equal(1, listBox.SelectedIndex);
  192. Assert.Equal("bar", listBox.SelectedItem);
  193. }
  194. [Fact]
  195. public void Setting_SelectedItem_Before_Initialize_Should_Retain_Selection()
  196. {
  197. var listBox = new ListBox
  198. {
  199. SelectionMode = SelectionMode.Single,
  200. ItemsSource = new[] { "foo", "bar", "baz" },
  201. SelectedItem = "bar"
  202. };
  203. listBox.BeginInit();
  204. listBox.EndInit();
  205. Assert.Equal(1, listBox.SelectedIndex);
  206. Assert.Equal("bar", listBox.SelectedItem);
  207. }
  208. [Fact]
  209. public void Setting_SelectedItems_Before_Initialize_Should_Retain_Selection()
  210. {
  211. var listBox = new ListBox
  212. {
  213. SelectionMode = SelectionMode.Multiple,
  214. ItemsSource = new[] { "foo", "bar", "baz" },
  215. };
  216. var selected = new[] { "foo", "bar" };
  217. foreach (var v in selected)
  218. {
  219. listBox.SelectedItems.Add(v);
  220. }
  221. listBox.BeginInit();
  222. listBox.EndInit();
  223. Assert.Equal(selected, listBox.SelectedItems);
  224. }
  225. [Fact]
  226. public void Setting_SelectedItems_During_Initialize_Should_Take_Priority_Over_Previous_Value()
  227. {
  228. var listBox = new ListBox
  229. {
  230. SelectionMode = SelectionMode.Multiple,
  231. ItemsSource = new[] { "foo", "bar", "baz" },
  232. };
  233. var selected = new[] { "foo", "bar" };
  234. foreach (var v in new[] { "bar", "baz" })
  235. {
  236. listBox.SelectedItems.Add(v);
  237. }
  238. listBox.BeginInit();
  239. listBox.SelectedItems = new AvaloniaList<object>(selected);
  240. listBox.EndInit();
  241. Assert.Equal(selected, listBox.SelectedItems);
  242. }
  243. [Fact]
  244. public void Setting_SelectedIndex_Before_Initialize_With_AlwaysSelected_Should_Retain_Selection()
  245. {
  246. var listBox = new ListBox
  247. {
  248. SelectionMode = SelectionMode.Single | SelectionMode.AlwaysSelected,
  249. ItemsSource = new[] { "foo", "bar", "baz" },
  250. SelectedIndex = 1
  251. };
  252. listBox.BeginInit();
  253. listBox.EndInit();
  254. Assert.Equal(1, listBox.SelectedIndex);
  255. Assert.Equal("bar", listBox.SelectedItem);
  256. }
  257. [Fact]
  258. public void Setting_SelectedIndex_Before_ApplyTemplate_Should_Set_Item_IsSelected_True()
  259. {
  260. var items = new[]
  261. {
  262. new Item(),
  263. new Item(),
  264. };
  265. var target = new SelectingItemsControl
  266. {
  267. ItemsSource = items,
  268. Template = Template(),
  269. };
  270. target.SelectedIndex = 1;
  271. Prepare(target);
  272. Assert.False(items[0].IsSelected);
  273. Assert.True(items[1].IsSelected);
  274. }
  275. [Fact]
  276. public void Setting_SelectedItem_Should_Set_SelectedIndex()
  277. {
  278. var items = new[]
  279. {
  280. new Item(),
  281. new Item(),
  282. };
  283. var target = new SelectingItemsControl
  284. {
  285. ItemsSource = items,
  286. Template = Template(),
  287. };
  288. target.ApplyTemplate();
  289. target.SelectedItem = items[1];
  290. Assert.Equal(items[1], target.SelectedItem);
  291. Assert.Equal(1, target.SelectedIndex);
  292. }
  293. [Fact]
  294. public void SelectedIndex_Item_Is_Updated_As_Items_Removed_When_Last_Item_Is_Selected()
  295. {
  296. var items = new ObservableCollection<string>
  297. {
  298. "Foo",
  299. "Bar",
  300. "FooBar"
  301. };
  302. var target = new SelectingItemsControl
  303. {
  304. ItemsSource = items,
  305. Template = Template(),
  306. };
  307. target.ApplyTemplate();
  308. target.SelectedItem = items[2];
  309. Assert.Equal(items[2], target.SelectedItem);
  310. Assert.Equal(2, target.SelectedIndex);
  311. items.RemoveAt(0);
  312. Assert.Equal(items[1], target.SelectedItem);
  313. Assert.Equal(1, target.SelectedIndex);
  314. }
  315. [Fact]
  316. public void Setting_SelectedItem_To_Not_Present_Item_Should_Clear_Selection()
  317. {
  318. var items = new[]
  319. {
  320. new Item(),
  321. new Item(),
  322. };
  323. var target = new SelectingItemsControl
  324. {
  325. ItemsSource = items,
  326. Template = Template(),
  327. };
  328. target.ApplyTemplate();
  329. target.SelectedItem = items[1];
  330. Assert.Equal(items[1], target.SelectedItem);
  331. Assert.Equal(1, target.SelectedIndex);
  332. target.SelectedItem = new Item();
  333. Assert.Null(target.SelectedItem);
  334. Assert.Equal(-1, target.SelectedIndex);
  335. }
  336. [Fact]
  337. public void Setting_SelectedIndex_Should_Set_SelectedItem()
  338. {
  339. var items = new[]
  340. {
  341. new Item(),
  342. new Item(),
  343. };
  344. var target = new SelectingItemsControl
  345. {
  346. ItemsSource = items,
  347. Template = Template(),
  348. };
  349. target.ApplyTemplate();
  350. target.SelectedIndex = 1;
  351. Assert.Equal(items[1], target.SelectedItem);
  352. }
  353. [Fact]
  354. public void Setting_SelectedIndex_Out_Of_Bounds_Should_Clear_Selection()
  355. {
  356. var items = new[]
  357. {
  358. new Item(),
  359. new Item(),
  360. };
  361. var target = new SelectingItemsControl
  362. {
  363. ItemsSource = items,
  364. Template = Template(),
  365. };
  366. target.ApplyTemplate();
  367. target.SelectedIndex = 2;
  368. Assert.Equal(-1, target.SelectedIndex);
  369. }
  370. [Fact]
  371. public void Setting_SelectedItem_To_Non_Existent_Item_Should_Clear_Selection()
  372. {
  373. var target = new SelectingItemsControl
  374. {
  375. Template = Template(),
  376. };
  377. target.ApplyTemplate();
  378. target.SelectedItem = new Item();
  379. Assert.Equal(-1, target.SelectedIndex);
  380. Assert.Null(target.SelectedItem);
  381. }
  382. [Fact]
  383. public void Adding_Selected_Item_Should_Update_Selection()
  384. {
  385. var items = new AvaloniaList<Item>(new[]
  386. {
  387. new Item(),
  388. new Item(),
  389. });
  390. var target = new SelectingItemsControl
  391. {
  392. ItemsSource = items,
  393. Template = Template(),
  394. };
  395. Prepare(target);
  396. items.Add(new Item { IsSelected = true });
  397. Assert.Equal(2, target.SelectedIndex);
  398. Assert.Equal(items[2], target.SelectedItem);
  399. }
  400. [Fact]
  401. public void Setting_Items_To_Null_Should_Clear_Selection()
  402. {
  403. var items = new AvaloniaList<Item>
  404. {
  405. new Item(),
  406. new Item(),
  407. };
  408. var target = new SelectingItemsControl
  409. {
  410. ItemsSource = items,
  411. Template = Template(),
  412. };
  413. target.ApplyTemplate();
  414. target.SelectedIndex = 1;
  415. Assert.Equal(items[1], target.SelectedItem);
  416. Assert.Equal(1, target.SelectedIndex);
  417. target.ItemsSource = null;
  418. Assert.Null(target.SelectedItem);
  419. Assert.Equal(-1, target.SelectedIndex);
  420. }
  421. [Fact]
  422. public void Removing_Selected_Item_Should_Clear_Selection()
  423. {
  424. var items = new AvaloniaList<Item>
  425. {
  426. new Item(),
  427. new Item(),
  428. };
  429. var target = new SelectingItemsControl
  430. {
  431. ItemsSource = items,
  432. Template = Template(),
  433. };
  434. Prepare(target);
  435. target.SelectedIndex = 1;
  436. Assert.Equal(items[1], target.SelectedItem);
  437. Assert.Equal(1, target.SelectedIndex);
  438. SelectionChangedEventArgs receivedArgs = null;
  439. target.SelectionChanged += (_, args) => receivedArgs = args;
  440. var removed = items[1];
  441. items.RemoveAt(1);
  442. Assert.Null(target.SelectedItem);
  443. Assert.Equal(-1, target.SelectedIndex);
  444. Assert.NotNull(receivedArgs);
  445. Assert.Empty(receivedArgs.AddedItems);
  446. Assert.Equal(new[] { removed }, receivedArgs.RemovedItems);
  447. Assert.False(items.Single().IsSelected);
  448. }
  449. [Fact]
  450. public void Removing_Selected_Item_Should_Update_Selection_With_AlwaysSelected()
  451. {
  452. var item0 = new Item();
  453. var item1 = new Item();
  454. var items = new AvaloniaList<Item>
  455. {
  456. item0,
  457. item1,
  458. };
  459. var target = new TestSelector
  460. {
  461. ItemsSource = items,
  462. Template = Template(),
  463. SelectionMode = SelectionMode.AlwaysSelected,
  464. };
  465. Prepare(target);
  466. target.SelectedIndex = 1;
  467. Assert.Equal(items[1], target.SelectedItem);
  468. Assert.Equal(1, target.SelectedIndex);
  469. SelectionChangedEventArgs receivedArgs = null;
  470. target.SelectionChanged += (_, args) => receivedArgs = args;
  471. items.RemoveAt(1);
  472. Assert.Same(item0, target.SelectedItem);
  473. Assert.Equal(0, target.SelectedIndex);
  474. Assert.NotNull(receivedArgs);
  475. Assert.Equal(new[] { item0 }, receivedArgs.AddedItems);
  476. Assert.Equal(new[] { item1 }, receivedArgs.RemovedItems);
  477. Assert.True(items.Single().IsSelected);
  478. }
  479. [Fact]
  480. public void Removing_Selected_Item_Should_Clear_Selection_With_BeginInit()
  481. {
  482. var items = new AvaloniaList<Item>
  483. {
  484. new Item(),
  485. new Item(),
  486. };
  487. var target = new SelectingItemsControl();
  488. target.BeginInit();
  489. target.ItemsSource = items;
  490. target.Template = Template();
  491. target.EndInit();
  492. Prepare(target);
  493. target.SelectedIndex = 0;
  494. Assert.Equal(items[0], target.SelectedItem);
  495. Assert.Equal(0, target.SelectedIndex);
  496. SelectionChangedEventArgs receivedArgs = null;
  497. target.SelectionChanged += (_, args) => receivedArgs = args;
  498. var removed = items[0];
  499. items.RemoveAt(0);
  500. Assert.Null(target.SelectedItem);
  501. Assert.Equal(-1, target.SelectedIndex);
  502. Assert.NotNull(receivedArgs);
  503. Assert.Empty(receivedArgs.AddedItems);
  504. Assert.Equal(new[] { removed }, receivedArgs.RemovedItems);
  505. Assert.False(items.Single().IsSelected);
  506. }
  507. [Fact]
  508. public void Replacing_Selected_Item_Should_Clear_Selection()
  509. {
  510. var items = new AvaloniaList<Item>
  511. {
  512. new Item(),
  513. new Item(),
  514. };
  515. var target = new SelectingItemsControl
  516. {
  517. ItemsSource = items,
  518. Template = Template(),
  519. };
  520. Prepare(target);
  521. target.SelectedIndex = 1;
  522. Assert.Equal(items[1], target.SelectedItem);
  523. Assert.Equal(1, target.SelectedIndex);
  524. SelectionChangedEventArgs receivedArgs = null;
  525. target.SelectionChanged += (_, args) => receivedArgs = args;
  526. var removed = items[1];
  527. items[1] = new Item();
  528. Assert.Null(target.SelectedItem);
  529. Assert.Equal(-1, target.SelectedIndex);
  530. Assert.NotNull(receivedArgs);
  531. Assert.Empty(receivedArgs.AddedItems);
  532. Assert.Equal(new[] { removed }, receivedArgs.RemovedItems);
  533. Assert.All(items, x => Assert.False(x.IsSelected));
  534. }
  535. [Fact]
  536. public void Moving_Selected_Item_Should_Clear_Selection()
  537. {
  538. var items = new AvaloniaList<Item>
  539. {
  540. new Item(),
  541. new Item(),
  542. };
  543. var target = new SelectingItemsControl
  544. {
  545. ItemsSource = items,
  546. Template = Template(),
  547. };
  548. Prepare(target);
  549. target.SelectedIndex = 1;
  550. Assert.Equal(items[1], target.SelectedItem);
  551. Assert.Equal(1, target.SelectedIndex);
  552. SelectionChangedEventArgs receivedArgs = null;
  553. target.SelectionChanged += (_, args) => receivedArgs = args;
  554. var removed = items[1];
  555. items.Move(1, 0);
  556. Assert.Null(target.SelectedItem);
  557. Assert.Equal(-1, target.SelectedIndex);
  558. Assert.NotNull(receivedArgs);
  559. Assert.Empty(receivedArgs.AddedItems);
  560. Assert.Equal(new[] { removed }, receivedArgs.RemovedItems);
  561. Assert.All(items, x => Assert.False(x.IsSelected));
  562. }
  563. [Fact]
  564. public void Resetting_Items_Collection_Should_Clear_Selection()
  565. {
  566. // Need to use ObservableCollection here as AvaloniaList signals a Clear as an
  567. // add + remove.
  568. var items = new ObservableCollection<Item>
  569. {
  570. new Item(),
  571. new Item(),
  572. };
  573. var target = new SelectingItemsControl
  574. {
  575. ItemsSource = items,
  576. Template = Template(),
  577. };
  578. target.ApplyTemplate();
  579. target.SelectedIndex = 1;
  580. Assert.Equal(items[1], target.SelectedItem);
  581. Assert.Equal(1, target.SelectedIndex);
  582. items.Clear();
  583. Assert.Null(target.SelectedItem);
  584. Assert.Equal(-1, target.SelectedIndex);
  585. }
  586. [Fact]
  587. public void Raising_IsSelectedChanged_On_Item_Should_Update_Selection()
  588. {
  589. var items = new[]
  590. {
  591. new Item(),
  592. new Item(),
  593. };
  594. var target = new SelectingItemsControl
  595. {
  596. ItemsSource = items,
  597. Template = Template(),
  598. };
  599. Prepare(target);
  600. target.SelectedItem = items[1];
  601. Assert.False(items[0].IsSelected);
  602. Assert.True(items[1].IsSelected);
  603. items[0].IsSelected = true;
  604. items[0].RaiseEvent(new RoutedEventArgs(SelectingItemsControl.IsSelectedChangedEvent));
  605. Assert.Equal(0, target.SelectedIndex);
  606. Assert.Equal(items[0], target.SelectedItem);
  607. Assert.True(items[0].IsSelected);
  608. Assert.False(items[1].IsSelected);
  609. }
  610. [Fact]
  611. public void Clearing_IsSelected_And_Raising_IsSelectedChanged_On_Item_Should_Update_Selection()
  612. {
  613. var items = new[]
  614. {
  615. new Item(),
  616. new Item(),
  617. };
  618. var target = new SelectingItemsControl
  619. {
  620. ItemsSource = items,
  621. Template = Template(),
  622. };
  623. Prepare(target);
  624. target.SelectedItem = items[1];
  625. Assert.False(items[0].IsSelected);
  626. Assert.True(items[1].IsSelected);
  627. items[1].IsSelected = false;
  628. items[1].RaiseEvent(new RoutedEventArgs(SelectingItemsControl.IsSelectedChangedEvent));
  629. Assert.Equal(-1, target.SelectedIndex);
  630. Assert.Null(target.SelectedItem);
  631. }
  632. [Fact]
  633. public void Raising_IsSelectedChanged_On_Someone_Elses_Item_Should_Not_Update_Selection()
  634. {
  635. var items = new[]
  636. {
  637. new Item(),
  638. new Item(),
  639. };
  640. var target = new SelectingItemsControl
  641. {
  642. ItemsSource = items,
  643. Template = Template(),
  644. };
  645. target.ApplyTemplate();
  646. target.SelectedItem = items[1];
  647. var notChild = new Item
  648. {
  649. IsSelected = true,
  650. };
  651. target.RaiseEvent(new RoutedEventArgs
  652. {
  653. RoutedEvent = SelectingItemsControl.IsSelectedChangedEvent,
  654. Source = notChild,
  655. });
  656. Assert.Equal(target.SelectedItem, items[1]);
  657. }
  658. [Fact]
  659. public void Setting_SelectedIndex_Should_Raise_SelectionChanged_Event()
  660. {
  661. var items = new[]
  662. {
  663. new Item(),
  664. new Item(),
  665. };
  666. var target = new SelectingItemsControl
  667. {
  668. ItemsSource = items,
  669. Template = Template(),
  670. };
  671. var called = false;
  672. target.SelectionChanged += (s, e) =>
  673. {
  674. Assert.Same(items[1], e.AddedItems.Cast<object>().Single());
  675. Assert.Empty(e.RemovedItems);
  676. called = true;
  677. };
  678. target.SelectedIndex = 1;
  679. Assert.True(called);
  680. }
  681. [Fact]
  682. public void Clearing_SelectedIndex_Should_Raise_SelectionChanged_Event()
  683. {
  684. var items = new[]
  685. {
  686. new Item(),
  687. new Item(),
  688. };
  689. var target = new SelectingItemsControl
  690. {
  691. ItemsSource = items,
  692. Template = Template(),
  693. SelectedIndex = 1,
  694. };
  695. Prepare(target);
  696. var called = false;
  697. target.SelectionChanged += (s, e) =>
  698. {
  699. Assert.Same(items[1], e.RemovedItems.Cast<object>().Single());
  700. Assert.Empty(e.AddedItems);
  701. called = true;
  702. };
  703. target.SelectedIndex = -1;
  704. Assert.True(called);
  705. }
  706. [Fact]
  707. public void Setting_SelectedIndex_Should_Raise_PropertyChanged_Events()
  708. {
  709. var items = new ObservableCollection<string> { "foo", "bar", "baz" };
  710. var target = new TestSelector
  711. {
  712. ItemsSource = items,
  713. Template = Template(),
  714. };
  715. var selectedIndexRaised = 0;
  716. var selectedItemRaised = 0;
  717. target.PropertyChanged += (s, e) =>
  718. {
  719. if (e.Property == SelectingItemsControl.SelectedIndexProperty)
  720. {
  721. Assert.Equal(-1, e.OldValue);
  722. Assert.Equal(1, e.NewValue);
  723. ++selectedIndexRaised;
  724. }
  725. else if (e.Property == SelectingItemsControl.SelectedItemProperty)
  726. {
  727. Assert.Null(e.OldValue);
  728. Assert.Equal("bar", e.NewValue);
  729. ++selectedItemRaised;
  730. }
  731. };
  732. target.SelectedIndex = 1;
  733. Assert.Equal(1, selectedIndexRaised);
  734. Assert.Equal(1, selectedItemRaised);
  735. }
  736. [Fact]
  737. public void Removing_Selected_Item_Should_Raise_PropertyChanged_Events()
  738. {
  739. var items = new ObservableCollection<string> { "foo", "bar", "baz" };
  740. var target = new TestSelector
  741. {
  742. ItemsSource = items,
  743. Template = Template(),
  744. };
  745. var selectedIndexRaised = 0;
  746. var selectedItemRaised = 0;
  747. target.SelectedIndex = 1;
  748. target.PropertyChanged += (s, e) =>
  749. {
  750. if (e.Property == SelectingItemsControl.SelectedIndexProperty)
  751. {
  752. Assert.Equal(1, e.OldValue);
  753. Assert.Equal(-1, e.NewValue);
  754. ++selectedIndexRaised;
  755. }
  756. else if (e.Property == SelectingItemsControl.SelectedItemProperty)
  757. {
  758. Assert.Equal("bar", e.OldValue);
  759. Assert.Null(e.NewValue);
  760. }
  761. };
  762. items.RemoveAt(1);
  763. Assert.Equal(1, selectedIndexRaised);
  764. Assert.Equal(0, selectedItemRaised);
  765. }
  766. [Fact]
  767. public void Removing_Selected_Item0_Should_Raise_PropertyChanged_Events_With_AlwaysSelected()
  768. {
  769. var items = new ObservableCollection<string> { "foo", "bar", "baz" };
  770. var target = new TestSelector
  771. {
  772. ItemsSource = items,
  773. Template = Template(),
  774. SelectionMode = SelectionMode.AlwaysSelected,
  775. };
  776. var selectedIndexRaised = 0;
  777. var selectedItemRaised = 0;
  778. target.SelectedIndex = 0;
  779. target.PropertyChanged += (s, e) =>
  780. {
  781. if (e.Property == SelectingItemsControl.SelectedIndexProperty)
  782. {
  783. ++selectedIndexRaised;
  784. }
  785. else if (e.Property == SelectingItemsControl.SelectedItemProperty)
  786. {
  787. Assert.Equal("foo", e.OldValue);
  788. Assert.Equal("bar", e.NewValue);
  789. ++selectedItemRaised;
  790. }
  791. };
  792. items.RemoveAt(0);
  793. Assert.Equal(0, selectedIndexRaised);
  794. Assert.Equal(1, selectedItemRaised);
  795. }
  796. [Fact]
  797. public void Removing_Selected_Item1_Should_Raise_PropertyChanged_Events_With_AlwaysSelected()
  798. {
  799. var items = new ObservableCollection<string> { "foo", "bar", "baz" };
  800. var target = new TestSelector
  801. {
  802. ItemsSource = items,
  803. Template = Template(),
  804. SelectionMode = SelectionMode.AlwaysSelected,
  805. };
  806. var selectedIndexRaised = 0;
  807. var selectedItemRaised = 0;
  808. target.SelectedIndex = 1;
  809. target.PropertyChanged += (s, e) =>
  810. {
  811. if (e.Property == SelectingItemsControl.SelectedIndexProperty)
  812. {
  813. Assert.Equal(1, e.OldValue);
  814. Assert.Equal(0, e.NewValue);
  815. ++selectedIndexRaised;
  816. }
  817. else if (e.Property == SelectingItemsControl.SelectedItemProperty)
  818. {
  819. Assert.Equal("bar", e.OldValue);
  820. Assert.Equal("foo", e.NewValue);
  821. }
  822. };
  823. items.RemoveAt(1);
  824. Assert.Equal(1, selectedIndexRaised);
  825. Assert.Equal(0, selectedItemRaised);
  826. }
  827. [Fact]
  828. public void Removing_Item_Before_Selection_Should_Raise_PropertyChanged_Events()
  829. {
  830. var items = new ObservableCollection<string> { "foo", "bar", "baz" };
  831. var target = new SelectingItemsControl
  832. {
  833. ItemsSource = items,
  834. Template = Template(),
  835. };
  836. var selectedIndexRaised = 0;
  837. var selectedItemRaised = 0;
  838. target.SelectedIndex = 1;
  839. target.PropertyChanged += (s, e) =>
  840. {
  841. if (e.Property == SelectingItemsControl.SelectedIndexProperty)
  842. {
  843. Assert.Equal(1, e.OldValue);
  844. Assert.Equal(0, e.NewValue);
  845. ++selectedIndexRaised;
  846. }
  847. else if (e.Property == SelectingItemsControl.SelectedItemProperty)
  848. {
  849. ++selectedItemRaised;
  850. }
  851. };
  852. items.RemoveAt(0);
  853. Assert.Equal(1, selectedIndexRaised);
  854. Assert.Equal(0, selectedItemRaised);
  855. }
  856. [Fact]
  857. public void Order_Of_Setting_Items_And_SelectedIndex_During_Initialization_Should_Not_Matter()
  858. {
  859. using var app = Start();
  860. var items = new[] { "Foo", "Bar" };
  861. var target = new SelectingItemsControl();
  862. ((ISupportInitialize)target).BeginInit();
  863. target.SelectedIndex = 1;
  864. target.ItemsSource = items;
  865. ((ISupportInitialize)target).EndInit();
  866. Prepare(target);
  867. Assert.Equal(1, target.SelectedIndex);
  868. Assert.Equal("Bar", target.SelectedItem);
  869. }
  870. [Fact]
  871. public void Order_Of_Setting_Items_And_SelectedItem_During_Initialization_Should_Not_Matter()
  872. {
  873. using var app = Start();
  874. var items = new[] { "Foo", "Bar" };
  875. var target = new SelectingItemsControl();
  876. ((ISupportInitialize)target).BeginInit();
  877. target.SelectedItem = "Bar";
  878. target.ItemsSource = items;
  879. ((ISupportInitialize)target).EndInit();
  880. Prepare(target);
  881. Assert.Equal(1, target.SelectedIndex);
  882. Assert.Equal("Bar", target.SelectedItem);
  883. }
  884. [Fact]
  885. public void Changing_DataContext_Should_Not_Clear_Nested_ViewModel_SelectedItem()
  886. {
  887. var items = new[]
  888. {
  889. new Item(),
  890. new Item(),
  891. };
  892. var vm = new MasterViewModel
  893. {
  894. Child = new ChildViewModel
  895. {
  896. Items = items,
  897. SelectedItem = items[1],
  898. }
  899. };
  900. var target = new SelectingItemsControl { DataContext = vm };
  901. var itemsBinding = new Binding("Child.Items");
  902. var selectedBinding = new Binding("Child.SelectedItem");
  903. target.Bind(SelectingItemsControl.ItemsSourceProperty, itemsBinding);
  904. target.Bind(SelectingItemsControl.SelectedItemProperty, selectedBinding);
  905. Assert.Equal(1, target.SelectedIndex);
  906. Assert.Same(vm.Child.SelectedItem, target.SelectedItem);
  907. items = new[]
  908. {
  909. new Item { Value = "Item1" },
  910. new Item { Value = "Item2" },
  911. new Item { Value = "Item3" },
  912. };
  913. vm = new MasterViewModel
  914. {
  915. Child = new ChildViewModel
  916. {
  917. Items = items,
  918. SelectedItem = items[2],
  919. }
  920. };
  921. target.DataContext = vm;
  922. Assert.Equal(2, target.SelectedIndex);
  923. Assert.Same(vm.Child.SelectedItem, target.SelectedItem);
  924. }
  925. [Fact]
  926. public void Nested_ListBox_Does_Not_Change_Parent_SelectedIndex()
  927. {
  928. SelectingItemsControl nested;
  929. var root = new SelectingItemsControl
  930. {
  931. Template = Template(),
  932. ItemsSource = new Control[]
  933. {
  934. new Border(),
  935. nested = new ListBox
  936. {
  937. Template = Template(),
  938. ItemsSource = new[] { "foo", "bar" },
  939. SelectedIndex = 1,
  940. }
  941. },
  942. SelectedIndex = 0,
  943. };
  944. root.ApplyTemplate();
  945. root.Presenter.ApplyTemplate();
  946. nested.ApplyTemplate();
  947. nested.Presenter.ApplyTemplate();
  948. Assert.Equal(0, root.SelectedIndex);
  949. Assert.Equal(1, nested.SelectedIndex);
  950. nested.SelectedIndex = 0;
  951. Assert.Equal(0, root.SelectedIndex);
  952. }
  953. [Fact]
  954. public void Setting_SelectedItem_With_Pointer_Should_Set_TabOnceActiveElement()
  955. {
  956. using (UnitTestApplication.Start())
  957. {
  958. var target = new ListBox
  959. {
  960. Template = Template(),
  961. ItemsSource = new[] { "Foo", "Bar", "Baz " },
  962. };
  963. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  964. Prepare(target);
  965. _helper.Down((Interactive)target.Presenter.Panel.Children[1]);
  966. var panel = target.Presenter.Panel;
  967. Assert.Equal(
  968. KeyboardNavigation.GetTabOnceActiveElement((InputElement)panel),
  969. panel.Children[1]);
  970. }
  971. }
  972. [Fact]
  973. public void Removing_SelectedItem_Should_Clear_TabOnceActiveElement()
  974. {
  975. using (UnitTestApplication.Start())
  976. {
  977. var items = new ObservableCollection<string>(new[] { "Foo", "Bar", "Baz " });
  978. var target = new ListBox
  979. {
  980. Template = Template(),
  981. ItemsSource = items,
  982. };
  983. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  984. Prepare(target);
  985. _helper.Down(target.Presenter.Panel.Children[1]);
  986. items.RemoveAt(1);
  987. var panel = target.Presenter.Panel;
  988. Assert.Null(KeyboardNavigation.GetTabOnceActiveElement((InputElement)panel));
  989. }
  990. }
  991. [Fact]
  992. public void Resetting_Items_Collection_Should_Retain_Selection()
  993. {
  994. var itemsMock = new Mock<List<string>>();
  995. var itemsMockAsINCC = itemsMock.As<INotifyCollectionChanged>();
  996. itemsMock.Object.AddRange(new[] { "Foo", "Bar", "Baz" });
  997. var target = new SelectingItemsControl
  998. {
  999. ItemsSource = itemsMock.Object
  1000. };
  1001. target.SelectedIndex = 1;
  1002. itemsMockAsINCC.Raise(e => e.CollectionChanged += null, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
  1003. Assert.True(target.SelectedIndex == 1);
  1004. }
  1005. [Fact]
  1006. public void Binding_With_DelayedBinding_And_Initialization_Where_DataContext_Is_Root_Works()
  1007. {
  1008. // Test for #1932.
  1009. var root = new RootWithItems();
  1010. root.BeginInit();
  1011. root.DataContext = root;
  1012. var target = new ListBox();
  1013. target.BeginInit();
  1014. root.Child = target;
  1015. DelayedBinding.Add(target, ItemsControl.ItemsSourceProperty, new Binding(nameof(RootWithItems.Items)));
  1016. DelayedBinding.Add(target, ListBox.SelectedItemProperty, new Binding(nameof(RootWithItems.Selected)));
  1017. target.EndInit();
  1018. root.EndInit();
  1019. Assert.Equal("b", target.SelectedItem);
  1020. }
  1021. [Fact]
  1022. public void Mode_For_SelectedIndex_Is_TwoWay_By_Default()
  1023. {
  1024. var items = new[]
  1025. {
  1026. new Item(),
  1027. new Item(),
  1028. new Item(),
  1029. };
  1030. var vm = new MasterViewModel
  1031. {
  1032. Child = new ChildViewModel
  1033. {
  1034. Items = items,
  1035. SelectedIndex = 1,
  1036. }
  1037. };
  1038. var target = new SelectingItemsControl { DataContext = vm };
  1039. var itemsBinding = new Binding("Child.Items");
  1040. var selectedIndBinding = new Binding("Child.SelectedIndex");
  1041. target.Bind(SelectingItemsControl.ItemsSourceProperty, itemsBinding);
  1042. target.Bind(SelectingItemsControl.SelectedIndexProperty, selectedIndBinding);
  1043. Assert.Equal(1, target.SelectedIndex);
  1044. target.SelectedIndex = 2;
  1045. Assert.Equal(2, target.SelectedIndex);
  1046. Assert.Equal(2, vm.Child.SelectedIndex);
  1047. }
  1048. [Fact]
  1049. public void Should_Select_Correct_Item_When_Duplicate_Items_Are_Present()
  1050. {
  1051. using (UnitTestApplication.Start())
  1052. {
  1053. var target = new ListBox
  1054. {
  1055. Template = Template(),
  1056. ItemsSource = new[] { "Foo", "Bar", "Baz", "Foo", "Bar", "Baz" },
  1057. };
  1058. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  1059. Prepare(target);
  1060. _helper.Down((Interactive)target.Presenter.Panel.Children[3]);
  1061. Assert.Equal(3, target.SelectedIndex);
  1062. }
  1063. }
  1064. [Fact]
  1065. public void Should_Apply_Selected_Pseudoclass_To_Correct_Item_When_Duplicate_Items_Are_Present()
  1066. {
  1067. using (UnitTestApplication.Start())
  1068. {
  1069. var target = new ListBox
  1070. {
  1071. Template = Template(),
  1072. ItemsSource = new[] { "Foo", "Bar", "Baz", "Foo", "Bar", "Baz" },
  1073. };
  1074. AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().Object);
  1075. Prepare(target);
  1076. _helper.Down((Interactive)target.Presenter.Panel.Children[3]);
  1077. Assert.Equal(new[] { ":pressed", ":selected" }, target.Presenter.Panel.Children[3].Classes);
  1078. }
  1079. }
  1080. [Fact]
  1081. public void Adding_Item_Before_SelectedItem_Should_Update_SelectedIndex()
  1082. {
  1083. var items = new ObservableCollection<string>
  1084. {
  1085. "Foo",
  1086. "Bar",
  1087. "Baz"
  1088. };
  1089. var target = new ListBox
  1090. {
  1091. Template = Template(),
  1092. ItemsSource = items,
  1093. SelectedIndex = 1,
  1094. };
  1095. Prepare(target);
  1096. items.Insert(0, "Qux");
  1097. Assert.Equal(2, target.SelectedIndex);
  1098. Assert.Equal("Bar", target.SelectedItem);
  1099. }
  1100. [Fact]
  1101. public void Removing_Item_Before_SelectedItem_Should_Update_SelectedIndex()
  1102. {
  1103. var items = new ObservableCollection<string>
  1104. {
  1105. "Foo",
  1106. "Bar",
  1107. "Baz"
  1108. };
  1109. var target = new ListBox
  1110. {
  1111. Template = Template(),
  1112. ItemsSource = items,
  1113. SelectedIndex = 1,
  1114. };
  1115. Prepare(target);
  1116. items.RemoveAt(0);
  1117. Assert.Equal(0, target.SelectedIndex);
  1118. Assert.Equal("Bar", target.SelectedItem);
  1119. }
  1120. [Fact]
  1121. public void Binding_SelectedIndex_Selects_Correct_Item()
  1122. {
  1123. // Issue #4496 (part 2)
  1124. var items = new ObservableCollection<string>();
  1125. var other = new ListBox
  1126. {
  1127. Template = Template(),
  1128. ItemsSource = items,
  1129. SelectionMode = SelectionMode.AlwaysSelected,
  1130. };
  1131. var target = new ListBox
  1132. {
  1133. Template = Template(),
  1134. ItemsSource = items,
  1135. [!ListBox.SelectedIndexProperty] = other[!ListBox.SelectedIndexProperty],
  1136. };
  1137. Prepare(other);
  1138. Prepare(target);
  1139. items.Add("Foo");
  1140. Assert.Equal(0, other.SelectedIndex);
  1141. Assert.Equal(0, target.SelectedIndex);
  1142. }
  1143. [Fact]
  1144. public void Binding_SelectedItem_Selects_Correct_Item()
  1145. {
  1146. // Issue #4496 (part 2)
  1147. var items = new ObservableCollection<string>();
  1148. var other = new ListBox
  1149. {
  1150. Template = Template(),
  1151. ItemsSource = items,
  1152. SelectionMode = SelectionMode.AlwaysSelected,
  1153. };
  1154. var target = new ListBox
  1155. {
  1156. Template = Template(),
  1157. ItemsSource = items,
  1158. [!ListBox.SelectedItemProperty] = other[!ListBox.SelectedItemProperty],
  1159. };
  1160. Prepare(target);
  1161. other.ApplyTemplate();
  1162. other.Presenter.ApplyTemplate();
  1163. items.Add("Foo");
  1164. Assert.Equal(0, other.SelectedIndex);
  1165. Assert.Equal(0, target.SelectedIndex);
  1166. }
  1167. [Fact]
  1168. public void Replacing_Selected_Item_Should_Update_SelectedItem()
  1169. {
  1170. var items = new ObservableCollection<string>
  1171. {
  1172. "Foo",
  1173. "Bar",
  1174. "Baz"
  1175. };
  1176. var target = new ListBox
  1177. {
  1178. Template = Template(),
  1179. ItemsSource = items,
  1180. SelectedIndex = 1,
  1181. };
  1182. Prepare(target);
  1183. items[1] = "Qux";
  1184. Assert.Equal(-1, target.SelectedIndex);
  1185. Assert.Null(target.SelectedItem);
  1186. }
  1187. [Fact]
  1188. public void AutoScrollToSelectedItem_Causes_Scroll_To_SelectedItem()
  1189. {
  1190. var items = new ObservableCollection<string>
  1191. {
  1192. "Foo",
  1193. "Bar",
  1194. "Baz"
  1195. };
  1196. var target = new ListBox
  1197. {
  1198. Template = Template(),
  1199. ItemsSource = items,
  1200. };
  1201. var raised = false;
  1202. Prepare(target);
  1203. target.AddHandler(Control.RequestBringIntoViewEvent, (s, e) => raised = true);
  1204. target.SelectedIndex = 2;
  1205. Assert.True(raised);
  1206. }
  1207. [Fact]
  1208. public void AutoScrollToSelectedItem_Causes_Scroll_To_Initial_SelectedItem()
  1209. {
  1210. var items = new ObservableCollection<string>
  1211. {
  1212. "Foo",
  1213. "Bar",
  1214. "Baz"
  1215. };
  1216. var target = new ListBox
  1217. {
  1218. Template = Template(),
  1219. ItemsSource = items,
  1220. };
  1221. var raised = false;
  1222. target.AddHandler(Control.RequestBringIntoViewEvent, (s, e) => raised = true);
  1223. target.SelectedIndex = 2;
  1224. Prepare(target);
  1225. Assert.True(raised);
  1226. }
  1227. [Fact]
  1228. public void AutoScrollToSelectedItem_On_Reset_Works()
  1229. {
  1230. // Issue #3148
  1231. using (UnitTestApplication.Start(TestServices.StyledWindow))
  1232. {
  1233. var items = new ResettingCollection(100);
  1234. var target = new ListBox
  1235. {
  1236. ItemsSource = items,
  1237. ItemTemplate = new FuncDataTemplate<string>((x, _) =>
  1238. new TextBlock
  1239. {
  1240. Text = x,
  1241. Width = 100,
  1242. Height = 10
  1243. }),
  1244. AutoScrollToSelectedItem = true,
  1245. };
  1246. var root = new TestRoot(true, target);
  1247. root.Measure(new Size(100, 100));
  1248. root.Arrange(new Rect(0, 0, 100, 100));
  1249. Assert.True(target.Presenter.Panel.Children.Count > 0);
  1250. Assert.True(target.Presenter.Panel.Children.Count < 100);
  1251. target.SelectedItem = "Item99";
  1252. // #3148 triggered here.
  1253. items.Reset(new[] { "Item99" });
  1254. Layout(target);
  1255. Assert.Equal(0, target.SelectedIndex);
  1256. Assert.Equal(1, target.Presenter.Panel.Children.Where(x => x.IsVisible).Count());
  1257. }
  1258. }
  1259. [Fact]
  1260. public void AutoScrollToSelectedItem_Scrolls_When_Reattached_To_Visual_Tree_If_Selection_Changed_While_Detached_From_Visual_Tree()
  1261. {
  1262. var items = new ObservableCollection<string>
  1263. {
  1264. "Foo",
  1265. "Bar",
  1266. "Baz"
  1267. };
  1268. var target = new ListBox
  1269. {
  1270. Template = Template(),
  1271. ItemsSource = items,
  1272. SelectedIndex = 2,
  1273. };
  1274. var raised = false;
  1275. Prepare(target);
  1276. var root = (TestRoot)target.Parent;
  1277. target.AddHandler(Control.RequestBringIntoViewEvent, (s, e) => raised = true);
  1278. root.Child = null;
  1279. target.SelectedIndex = 1;
  1280. root.Child = target;
  1281. Assert.True(raised);
  1282. }
  1283. [Fact]
  1284. public void AutoScrollToSelectedItem_Doesnt_Scroll_If_Reattached_To_Visual_Tree_With_No_Selection_Change()
  1285. {
  1286. var items = new ObservableCollection<string>
  1287. {
  1288. "Foo",
  1289. "Bar",
  1290. "Baz"
  1291. };
  1292. var target = new ListBox
  1293. {
  1294. Template = Template(),
  1295. ItemsSource = items,
  1296. SelectedIndex = 2,
  1297. };
  1298. var raised = false;
  1299. Prepare(target);
  1300. var root = (TestRoot)target.Parent;
  1301. target.AddHandler(Control.RequestBringIntoViewEvent, (s, e) => raised = true);
  1302. root.Child = null;
  1303. root.Child = target;
  1304. Assert.False(raised);
  1305. }
  1306. [Fact]
  1307. public void AutoScrollToSelectedItem_Causes_Scroll_When_Turned_On()
  1308. {
  1309. var items = new ObservableCollection<string>
  1310. {
  1311. "Foo",
  1312. "Bar",
  1313. "Baz"
  1314. };
  1315. var target = new ListBox
  1316. {
  1317. Template = Template(),
  1318. ItemsSource = items,
  1319. AutoScrollToSelectedItem = false,
  1320. };
  1321. Prepare(target);
  1322. var raised = false;
  1323. target.AddHandler(Control.RequestBringIntoViewEvent, (s, e) => raised = true);
  1324. target.SelectedIndex = 2;
  1325. Assert.False(raised);
  1326. target.AutoScrollToSelectedItem = true;
  1327. Assert.True(raised);
  1328. }
  1329. [Fact]
  1330. public void Can_Set_Both_SelectedItem_And_SelectedItems_During_Initialization()
  1331. {
  1332. // Issue #2969.
  1333. var target = new ListBox();
  1334. var selectedItems = new List<object>();
  1335. target.BeginInit();
  1336. target.Template = Template();
  1337. target.ItemsSource = new[] { "Foo", "Bar", "Baz" };
  1338. target.SelectedItems = selectedItems;
  1339. target.SelectedItem = "Bar";
  1340. target.EndInit();
  1341. Prepare(target);
  1342. Assert.Equal("Bar", target.SelectedItem);
  1343. Assert.Equal(1, target.SelectedIndex);
  1344. Assert.Same(selectedItems, target.SelectedItems);
  1345. Assert.Equal(new[] { "Bar" }, selectedItems);
  1346. }
  1347. [Fact(Timeout = 2000)]
  1348. public async Task MoveSelection_Wrap_Does_Not_Hang_With_No_Focusable_Controls()
  1349. {
  1350. // Issue #3094.
  1351. var target = new TestSelector
  1352. {
  1353. Template = Template(),
  1354. Items =
  1355. {
  1356. new ListBoxItem { Focusable = false },
  1357. new ListBoxItem { Focusable = false },
  1358. },
  1359. SelectedIndex = 0,
  1360. };
  1361. target.Measure(new Size(100, 100));
  1362. target.Arrange(new Rect(0, 0, 100, 100));
  1363. // Timeout in xUnit doesn't work with synchronous methods so we need to apply hack below.
  1364. // https://github.com/xunit/xunit/issues/2222
  1365. await Task.Run(() => target.MoveSelection(NavigationDirection.Next, true));
  1366. }
  1367. [Fact]
  1368. public void MoveSelection_Skips_Non_Focusable_Controls_When_Moving_To_Last_Item()
  1369. {
  1370. var target = new TestSelector
  1371. {
  1372. Template = Template(),
  1373. Items =
  1374. {
  1375. new ListBoxItem(),
  1376. new ListBoxItem { Focusable = false },
  1377. }
  1378. };
  1379. target.Measure(new Size(100, 100));
  1380. target.Arrange(new Rect(0, 0, 100, 100));
  1381. target.MoveSelection(NavigationDirection.Last, true);
  1382. Assert.Equal(0, target.SelectedIndex);
  1383. }
  1384. [Fact]
  1385. public void MoveSelection_Skips_Non_Focusable_Controls_When_Moving_To_First_Item()
  1386. {
  1387. var target = new TestSelector
  1388. {
  1389. Template = Template(),
  1390. Items =
  1391. {
  1392. new ListBoxItem { Focusable = false },
  1393. new ListBoxItem(),
  1394. }
  1395. };
  1396. target.Measure(new Size(100, 100));
  1397. target.Arrange(new Rect(0, 0, 100, 100));
  1398. target.MoveSelection(NavigationDirection.Last, true);
  1399. Assert.Equal(1, target.SelectedIndex);
  1400. }
  1401. [Fact(Timeout = 2000)]
  1402. public async Task MoveSelection_Does_Not_Hang_When_All_Items_Are_Non_Focusable_And_We_Move_To_First_Item()
  1403. {
  1404. var target = new TestSelector
  1405. {
  1406. Template = Template(),
  1407. Items =
  1408. {
  1409. new ListBoxItem { Focusable = false },
  1410. new ListBoxItem { Focusable = false },
  1411. }
  1412. };
  1413. target.Measure(new Size(100, 100));
  1414. target.Arrange(new Rect(0, 0, 100, 100));
  1415. // Timeout in xUnit doesn't work with synchronous methods so we need to apply hack below.
  1416. // https://github.com/xunit/xunit/issues/2222
  1417. await Task.Run(() => target.MoveSelection(NavigationDirection.First, true));
  1418. Assert.Equal(-1, target.SelectedIndex);
  1419. }
  1420. [Fact(Timeout = 2000)]
  1421. public async Task MoveSelection_Does_Not_Hang_When_All_Items_Are_Non_Focusable_And_We_Move_To_Last_Item()
  1422. {
  1423. var target = new TestSelector
  1424. {
  1425. Template = Template(),
  1426. Items =
  1427. {
  1428. new ListBoxItem { Focusable = false },
  1429. new ListBoxItem { Focusable = false },
  1430. }
  1431. };
  1432. target.Measure(new Size(100, 100));
  1433. target.Arrange(new Rect(0, 0, 100, 100));
  1434. // Timeout in xUnit doesn't work with synchronous methods so we need to apply hack below.
  1435. // https://github.com/xunit/xunit/issues/2222
  1436. await Task.Run(() => target.MoveSelection(NavigationDirection.Last, true));
  1437. Assert.Equal(-1, target.SelectedIndex);
  1438. }
  1439. [Fact]
  1440. public void MoveSelection_Does_Select_Disabled_Controls()
  1441. {
  1442. // Issue #3426.
  1443. var target = new TestSelector
  1444. {
  1445. Template = Template(),
  1446. Items =
  1447. {
  1448. new ListBoxItem(),
  1449. new ListBoxItem { IsEnabled = false },
  1450. },
  1451. SelectedIndex = 0,
  1452. };
  1453. target.Measure(new Size(100, 100));
  1454. target.Arrange(new Rect(0, 0, 100, 100));
  1455. target.MoveSelection(NavigationDirection.Next, true);
  1456. Assert.Equal(0, target.SelectedIndex);
  1457. }
  1458. [Fact]
  1459. public void Pre_Selecting_Item_Should_Set_Selection_After_It_Was_Added_When_AlwaysSelected()
  1460. {
  1461. var target = new TestSelector(SelectionMode.AlwaysSelected)
  1462. {
  1463. Template = Template()
  1464. };
  1465. var second = new Item { IsSelected = true };
  1466. var items = new AvaloniaList<object>
  1467. {
  1468. new Item(),
  1469. second
  1470. };
  1471. target.ItemsSource = items;
  1472. Prepare(target);
  1473. Assert.Equal(second, target.SelectedItem);
  1474. Assert.Equal(1, target.SelectedIndex);
  1475. }
  1476. [Fact]
  1477. public void Setting_SelectionMode_Should_Update_SelectionModel()
  1478. {
  1479. var target = new TestSelector();
  1480. var model = target.Selection;
  1481. Assert.True(model.SingleSelect);
  1482. target.SelectionMode = SelectionMode.Multiple;
  1483. Assert.False(model.SingleSelect);
  1484. }
  1485. [Fact]
  1486. public void Does_The_Best_It_Can_With_AutoSelecting_ViewModel()
  1487. {
  1488. // Tests the following scenario:
  1489. //
  1490. // - Items changes from empty to having 1 item
  1491. // - ViewModel auto-selects item 0 in CollectionChanged
  1492. // - SelectionModel receives CollectionChanged
  1493. // - And so adjusts the selected item from 0 to 1, which is past the end of the items.
  1494. //
  1495. // There's not much we can do about this situation because the order in which
  1496. // CollectionChanged handlers are called can't be known (the problem also exists with
  1497. // WPF). The best we can do is not select an invalid index.
  1498. var vm = new SelectionViewModel();
  1499. vm.Items.CollectionChanged += (s, e) =>
  1500. {
  1501. if (vm.SelectedIndex == -1 && vm.Items.Count > 0)
  1502. {
  1503. vm.SelectedIndex = 0;
  1504. }
  1505. };
  1506. var target = new ListBox
  1507. {
  1508. [!ListBox.ItemsSourceProperty] = new Binding("Items"),
  1509. [!ListBox.SelectedIndexProperty] = new Binding("SelectedIndex"),
  1510. DataContext = vm,
  1511. };
  1512. Prepare(target);
  1513. vm.Items.Add("foo");
  1514. vm.Items.Add("bar");
  1515. Assert.Equal(0, target.SelectedIndex);
  1516. Assert.Equal(new[] { 0 }, target.Selection.SelectedIndexes);
  1517. Assert.Equal("foo", target.SelectedItem);
  1518. Assert.Equal(new[] { "foo" }, target.SelectedItems);
  1519. }
  1520. [Fact]
  1521. public void Preserves_Initial_SelectedItems_When_Bound()
  1522. {
  1523. // Issue #4272 (there are two issues there, this addresses the second one).
  1524. var vm = new SelectionViewModel
  1525. {
  1526. Items = { "foo", "bar", "baz" },
  1527. SelectedItems = { "bar" },
  1528. };
  1529. var target = new ListBox
  1530. {
  1531. [!ListBox.ItemsSourceProperty] = new Binding("Items"),
  1532. [!ListBox.SelectedItemsProperty] = new Binding("SelectedItems"),
  1533. DataContext = vm,
  1534. };
  1535. Prepare(target);
  1536. Assert.Equal(1, target.SelectedIndex);
  1537. Assert.Equal(new[] { 1 }, target.Selection.SelectedIndexes);
  1538. Assert.Equal("bar", target.SelectedItem);
  1539. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  1540. }
  1541. [Fact]
  1542. public void Preserves_SelectedItem_When_Items_Changed()
  1543. {
  1544. // Issue #4048
  1545. using var app = Start();
  1546. var target = new SelectingItemsControl
  1547. {
  1548. ItemsSource = new[] { "foo", "bar", "baz"},
  1549. SelectedItem = "bar",
  1550. };
  1551. Prepare(target);
  1552. Assert.Equal(1, target.SelectedIndex);
  1553. Assert.Equal("bar", target.SelectedItem);
  1554. target.ItemsSource = new[] { "qux", "foo", "bar" };
  1555. Assert.Equal(2, target.SelectedIndex);
  1556. Assert.Equal("bar", target.SelectedItem);
  1557. }
  1558. [Fact]
  1559. public void Setting_SelectedItems_Raises_PropertyChanged()
  1560. {
  1561. using var app = Start();
  1562. var target = new TestSelector
  1563. {
  1564. ItemsSource = new[] { "foo", "bar", "baz" },
  1565. };
  1566. var raised = 0;
  1567. var newValue = new AvaloniaList<object>();
  1568. Prepare(target);
  1569. target.PropertyChanged += (s, e) =>
  1570. {
  1571. if (e.Property == ListBox.SelectedItemsProperty)
  1572. {
  1573. Assert.Null(e.OldValue);
  1574. Assert.Same(newValue, e.NewValue);
  1575. ++raised;
  1576. }
  1577. };
  1578. target.SelectedItems = newValue;
  1579. Assert.Equal(1, raised);
  1580. }
  1581. [Fact]
  1582. public void Setting_Selection_Raises_SelectedItems_PropertyChanged()
  1583. {
  1584. using var app = Start();
  1585. var target = new TestSelector
  1586. {
  1587. ItemsSource = new[] { "foo", "bar", "baz" },
  1588. };
  1589. var raised = 0;
  1590. var oldValue = target.SelectedItems;
  1591. Prepare(target);
  1592. target.PropertyChanged += (s, e) =>
  1593. {
  1594. if (e.Property == ListBox.SelectedItemsProperty)
  1595. {
  1596. Assert.Same(oldValue, e.OldValue);
  1597. Assert.Null(e.NewValue);
  1598. ++raised;
  1599. }
  1600. };
  1601. target.Selection = new SelectionModel<int>();
  1602. Assert.Equal(1, raised);
  1603. }
  1604. [Fact]
  1605. public void Handles_Removing_Last_Item_In_Two_Controls_With_Bound_SelectedIndex()
  1606. {
  1607. var items = new ObservableCollection<string> { "foo" };
  1608. // Simulates problem with TabStrip and Carousel with bound SelectedIndex.
  1609. var tabStrip = new TestSelector
  1610. {
  1611. ItemsSource = items,
  1612. SelectionMode = SelectionMode.AlwaysSelected,
  1613. };
  1614. var carousel = new TestSelector
  1615. {
  1616. ItemsSource = items,
  1617. [!Carousel.SelectedIndexProperty] = tabStrip[!TabStrip.SelectedIndexProperty],
  1618. };
  1619. var tabStripRaised = 0;
  1620. var carouselRaised = 0;
  1621. tabStrip.SelectionChanged += (s, e) =>
  1622. {
  1623. Assert.Equal(new[] { "foo" }, e.RemovedItems);
  1624. Assert.Empty(e.AddedItems);
  1625. ++tabStripRaised;
  1626. };
  1627. carousel.SelectionChanged += (s, e) =>
  1628. {
  1629. Assert.Equal(new[] { "foo" }, e.RemovedItems);
  1630. Assert.Empty(e.AddedItems);
  1631. ++carouselRaised;
  1632. };
  1633. items.RemoveAt(0);
  1634. Assert.Equal(1, tabStripRaised);
  1635. Assert.Equal(1, carouselRaised);
  1636. }
  1637. [Fact]
  1638. public void Handles_Removing_Last_Item_In_Controls_With_Bound_SelectedItem()
  1639. {
  1640. var items = new ObservableCollection<string> { "foo" };
  1641. // Simulates problem with TabStrip and Carousel with bound SelectedItem.
  1642. var tabStrip = new TestSelector
  1643. {
  1644. ItemsSource = items,
  1645. SelectionMode = SelectionMode.AlwaysSelected,
  1646. };
  1647. var carousel = new TestSelector
  1648. {
  1649. ItemsSource = items,
  1650. [!Carousel.SelectedItemProperty] = tabStrip[!TabStrip.SelectedItemProperty],
  1651. };
  1652. var tabStripRaised = 0;
  1653. var carouselRaised = 0;
  1654. tabStrip.SelectionChanged += (s, e) =>
  1655. {
  1656. Assert.Equal(new[] { "foo" }, e.RemovedItems);
  1657. Assert.Empty(e.AddedItems);
  1658. ++tabStripRaised;
  1659. };
  1660. carousel.SelectionChanged += (s, e) =>
  1661. {
  1662. Assert.Equal(new[] { "foo" }, e.RemovedItems);
  1663. Assert.Empty(e.AddedItems);
  1664. ++carouselRaised;
  1665. };
  1666. items.RemoveAt(0);
  1667. Assert.Equal(1, tabStripRaised);
  1668. Assert.Equal(1, carouselRaised);
  1669. }
  1670. [Fact]
  1671. public void Setting_IsTextSearchEnabled_Enables_Or_Disables_Text_Search()
  1672. {
  1673. var pti = Mock.Of<IDispatcherImpl>(x => x.CurrentThreadIsLoopThread == true);
  1674. using (UnitTestApplication.Start(TestServices.StyledWindow.With(dispatcherImpl: pti)))
  1675. {
  1676. var items = new[]
  1677. {
  1678. new Item { [TextSearch.TextProperty] = "Foo" },
  1679. new Item { [TextSearch.TextProperty] = "Bar" }
  1680. };
  1681. var target = new SelectingItemsControl
  1682. {
  1683. ItemsSource = items,
  1684. Template = Template(),
  1685. IsTextSearchEnabled = false
  1686. };
  1687. Prepare(target);
  1688. target.RaiseEvent(new TextInputEventArgs
  1689. {
  1690. RoutedEvent = InputElement.TextInputEvent,
  1691. Device = KeyboardDevice.Instance,
  1692. Text = "Foo"
  1693. });
  1694. Assert.Null(target.SelectedItem);
  1695. target.IsTextSearchEnabled = true;
  1696. target.RaiseEvent(new TextInputEventArgs
  1697. {
  1698. RoutedEvent = InputElement.TextInputEvent,
  1699. Device = KeyboardDevice.Instance,
  1700. Text = "Foo"
  1701. });
  1702. Assert.Equal(items[0], target.SelectedItem);
  1703. }
  1704. }
  1705. private static IDisposable Start()
  1706. {
  1707. return UnitTestApplication.Start(TestServices.StyledWindow);
  1708. }
  1709. private static void Prepare(SelectingItemsControl target)
  1710. {
  1711. var root = new TestRoot
  1712. {
  1713. Child = target,
  1714. Width = 100,
  1715. Height = 100,
  1716. Styles =
  1717. {
  1718. new Style(x => x.Is<SelectingItemsControl>())
  1719. {
  1720. Setters =
  1721. {
  1722. new Setter(ListBox.TemplateProperty, Template()),
  1723. },
  1724. },
  1725. },
  1726. };
  1727. root.LayoutManager.ExecuteInitialLayoutPass();
  1728. }
  1729. private static void Layout(Control c)
  1730. {
  1731. ((ILayoutRoot)c.GetVisualRoot()).LayoutManager.ExecuteLayoutPass();
  1732. }
  1733. private static FuncControlTemplate Template()
  1734. {
  1735. return new FuncControlTemplate<SelectingItemsControl>((control, scope) =>
  1736. new ItemsPresenter
  1737. {
  1738. Name = "itemsPresenter",
  1739. [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty],
  1740. }.RegisterInNameScope(scope));
  1741. }
  1742. private class Item : Control, ISelectable
  1743. {
  1744. public string Value { get; set; }
  1745. public bool IsSelected
  1746. {
  1747. get => SelectingItemsControl.GetIsSelected(this);
  1748. set => SelectingItemsControl.SetIsSelected(this, value);
  1749. }
  1750. }
  1751. private class MasterViewModel : NotifyingBase
  1752. {
  1753. private ChildViewModel _child;
  1754. public ChildViewModel Child
  1755. {
  1756. get { return _child; }
  1757. set
  1758. {
  1759. _child = value;
  1760. RaisePropertyChanged();
  1761. }
  1762. }
  1763. }
  1764. private class ChildViewModel : NotifyingBase
  1765. {
  1766. public IList<Item> Items { get; set; }
  1767. public Item SelectedItem { get; set; }
  1768. public int SelectedIndex { get; set; }
  1769. }
  1770. private class SelectionViewModel : NotifyingBase
  1771. {
  1772. private int _selectedIndex = -1;
  1773. public SelectionViewModel()
  1774. {
  1775. Items = new ObservableCollection<string>();
  1776. SelectedItems = new ObservableCollection<string>();
  1777. }
  1778. public int SelectedIndex
  1779. {
  1780. get => _selectedIndex;
  1781. set
  1782. {
  1783. _selectedIndex = value;
  1784. RaisePropertyChanged();
  1785. }
  1786. }
  1787. public ObservableCollection<string> Items { get; }
  1788. public ObservableCollection<string> SelectedItems { get; }
  1789. }
  1790. private class RootWithItems : TestRoot
  1791. {
  1792. public List<string> Items { get; set; } = new List<string>() { "a", "b", "c", "d", "e" };
  1793. public string Selected { get; set; } = "b";
  1794. }
  1795. private class TestSelector : SelectingItemsControl
  1796. {
  1797. public TestSelector()
  1798. {
  1799. }
  1800. public TestSelector(SelectionMode selectionMode)
  1801. {
  1802. SelectionMode = selectionMode;
  1803. }
  1804. public new ISelectionModel Selection
  1805. {
  1806. get => base.Selection;
  1807. set => base.Selection = value;
  1808. }
  1809. public new IList SelectedItems
  1810. {
  1811. get => base.SelectedItems;
  1812. set => base.SelectedItems = value;
  1813. }
  1814. public new SelectionMode SelectionMode
  1815. {
  1816. get => base.SelectionMode;
  1817. set => base.SelectionMode = value;
  1818. }
  1819. public new bool MoveSelection(NavigationDirection direction, bool wrap)
  1820. {
  1821. return base.MoveSelection(direction, wrap);
  1822. }
  1823. }
  1824. private class ResettingCollection : List<string>, INotifyCollectionChanged
  1825. {
  1826. public ResettingCollection(int itemCount)
  1827. {
  1828. AddRange(Enumerable.Range(0, itemCount).Select(x => $"Item{x}"));
  1829. }
  1830. public void Reset(IEnumerable<string> items)
  1831. {
  1832. Clear();
  1833. AddRange(items);
  1834. CollectionChanged?.Invoke(
  1835. this,
  1836. new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
  1837. }
  1838. public event NotifyCollectionChangedEventHandler CollectionChanged;
  1839. }
  1840. }
  1841. }