SelectionModelTests_Single.cs 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Specialized;
  4. using System.Linq;
  5. using Avalonia.Collections;
  6. using Avalonia.Controls.Selection;
  7. using Avalonia.Controls.Utils;
  8. using Avalonia.UnitTests;
  9. using Xunit;
  10. using CollectionChangedEventManager = Avalonia.Controls.Utils.CollectionChangedEventManager;
  11. #nullable enable
  12. namespace Avalonia.Controls.UnitTests.Selection
  13. {
  14. public class SelectionModelTests_Single
  15. {
  16. public class Source : ScopedTestBase
  17. {
  18. [Fact]
  19. public void Can_Select_Index_Before_Source_Assigned()
  20. {
  21. var target = CreateTarget(false);
  22. var raised = 0;
  23. target.SelectionChanged += (s, e) =>
  24. {
  25. Assert.Empty(e.DeselectedIndexes);
  26. Assert.Empty(e.DeselectedItems);
  27. Assert.Equal(new[] { 5 }, e.SelectedIndexes);
  28. Assert.Equal(new string?[] { null }, e.SelectedItems);
  29. ++raised;
  30. };
  31. target.SelectedIndex = 5;
  32. Assert.Equal(5, target.SelectedIndex);
  33. Assert.Equal(new[] { 5 }, target.SelectedIndexes);
  34. Assert.Null(target.SelectedItem);
  35. Assert.Equal(new string?[] { null }, target.SelectedItems);
  36. Assert.Equal(1, raised);
  37. }
  38. [Fact]
  39. public void Can_Select_Item_Before_Source_Assigned()
  40. {
  41. var target = CreateTarget(false);
  42. var raised = 0;
  43. target.SelectionChanged += (s, e) => ++raised;
  44. target.SelectedItem = "bar";
  45. Assert.Equal(-1, target.SelectedIndex);
  46. Assert.Empty(target.SelectedIndexes);
  47. Assert.Equal("bar", target.SelectedItem);
  48. Assert.Equal(new string?[] { "bar" }, target.SelectedItems);
  49. Assert.Equal(0, raised);
  50. }
  51. [Fact]
  52. public void Initializing_Source_Retains_Valid_Index_Selection()
  53. {
  54. var target = CreateTarget(false);
  55. var raised = 0;
  56. target.SelectedIndex = 1;
  57. target.SelectionChanged += (s, e) => ++raised;
  58. target.Source = new[] { "foo", "bar", "baz" };
  59. Assert.Equal(1, target.SelectedIndex);
  60. Assert.Equal(new[] { 1 }, target.SelectedIndexes);
  61. Assert.Equal("bar", target.SelectedItem);
  62. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  63. Assert.Equal(0, raised);
  64. }
  65. [Fact]
  66. public void Initializing_Source_Removes_Invalid_Index_Selection()
  67. {
  68. var target = CreateTarget(false);
  69. var raised = 0;
  70. target.SelectedIndex = 5;
  71. target.SelectionChanged += (s, e) =>
  72. {
  73. Assert.Equal(new[] { 5 }, e.DeselectedIndexes);
  74. Assert.Equal(new string?[] { null }, e.DeselectedItems);
  75. Assert.Empty(e.SelectedIndexes);
  76. Assert.Empty(e.SelectedItems);
  77. ++raised;
  78. };
  79. target.Source = new[] { "foo", "bar", "baz" };
  80. Assert.Equal(-1, target.SelectedIndex);
  81. Assert.Empty(target.SelectedIndexes);
  82. Assert.Null(target.SelectedItem);
  83. Assert.Empty(target.SelectedItems);
  84. Assert.Equal(1, raised);
  85. }
  86. [Fact]
  87. public void Initializing_Source_Retains_Valid_Item_Selection()
  88. {
  89. var target = CreateTarget(false);
  90. var raised = 0;
  91. target.SelectedItem = "bar";
  92. target.SelectionChanged += (s, e) =>
  93. {
  94. Assert.Empty(e.DeselectedIndexes);
  95. Assert.Empty(e.DeselectedItems);
  96. Assert.Equal(new[] { 1 }, e.SelectedIndexes);
  97. Assert.Equal(new string[] { "bar" }, e.SelectedItems);
  98. ++raised;
  99. };
  100. target.Source = new[] { "foo", "bar", "baz" };
  101. Assert.Equal(1, target.SelectedIndex);
  102. Assert.Equal(new[] { 1 }, target.SelectedIndexes);
  103. Assert.Equal("bar", target.SelectedItem);
  104. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  105. Assert.Equal(1, raised);
  106. }
  107. [Fact]
  108. public void Initializing_Source_Removes_Invalid_Item_Selection()
  109. {
  110. var target = CreateTarget(false);
  111. var raised = 0;
  112. target.SelectedItem = "qux";
  113. target.SelectionChanged += (s, e) => ++raised;
  114. target.Source = new[] { "foo", "bar", "baz" };
  115. Assert.Equal(-1, target.SelectedIndex);
  116. Assert.Empty(target.SelectedIndexes);
  117. Assert.Null(target.SelectedItem);
  118. Assert.Empty(target.SelectedItems);
  119. Assert.Equal(0, raised);
  120. }
  121. [Fact]
  122. public void Initializing_Source_Respects_SourceIndex_SourceItem_Order()
  123. {
  124. var target = CreateTarget(false);
  125. target.SelectedIndex = 0;
  126. target.SelectedItem = "bar";
  127. target.Source = new[] { "foo", "bar", "baz" };
  128. Assert.Equal(1, target.SelectedIndex);
  129. Assert.Equal(new[] { 1 }, target.SelectedIndexes);
  130. Assert.Equal("bar", target.SelectedItem);
  131. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  132. }
  133. [Fact]
  134. public void Initializing_Source_Respects_SourceItem_SourceIndex_Order()
  135. {
  136. var target = CreateTarget(false);
  137. target.SelectedItem = "foo";
  138. target.SelectedIndex = 1;
  139. target.Source = new[] { "foo", "bar", "baz" };
  140. Assert.Equal(1, target.SelectedIndex);
  141. Assert.Equal(new[] { 1 }, target.SelectedIndexes);
  142. Assert.Equal("bar", target.SelectedItem);
  143. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  144. }
  145. [Fact]
  146. public void Initializing_Source_Raises_SelectedItems_PropertyChanged()
  147. {
  148. var target = CreateTarget(false);
  149. var selectedItemRaised = 0;
  150. var selectedItemsRaised = 0;
  151. target.Select(1);
  152. target.PropertyChanged += (s, e) =>
  153. {
  154. if (e.PropertyName == nameof(target.SelectedItem))
  155. {
  156. ++selectedItemRaised;
  157. }
  158. else if (e.PropertyName == nameof(target.SelectedItems))
  159. {
  160. ++selectedItemsRaised;
  161. }
  162. };
  163. target.Source = new[] { "foo", "bar", "baz" };
  164. Assert.Equal(1, selectedItemRaised);
  165. Assert.Equal(1, selectedItemsRaised);
  166. }
  167. [Fact]
  168. public void Changing_Source_To_Null_Doesnt_Clear_Selection()
  169. {
  170. var target = CreateTarget();
  171. var raised = 0;
  172. target.SelectedIndex = 2;
  173. target.SelectionChanged += (s, e) => ++raised;
  174. target.Source = null;
  175. Assert.Equal(2, target.SelectedIndex);
  176. Assert.Equal(new[] { 2 }, target.SelectedIndexes);
  177. Assert.Null(target.SelectedItem);
  178. Assert.Equal(new string?[] { null }, target.SelectedItems);
  179. Assert.Equal(0, raised);
  180. }
  181. [Fact]
  182. public void Changing_Source_To_NonNull_First_Clears_Old_Selection()
  183. {
  184. var target = CreateTarget();
  185. var raised = 0;
  186. target.SelectedIndex = 2;
  187. target.SelectionChanged += (s, e) =>
  188. {
  189. Assert.Equal(new[] { 2 }, e.DeselectedIndexes);
  190. Assert.Equal(new string?[] { "baz" }, e.DeselectedItems);
  191. Assert.Empty(e.SelectedIndexes);
  192. Assert.Empty(e.SelectedItems);
  193. ++raised;
  194. };
  195. target.Source = new[] { "qux", "quux", "corge" };
  196. Assert.Equal(-1, target.SelectedIndex);
  197. Assert.Empty(target.SelectedIndexes);
  198. Assert.Null(target.SelectedItem);
  199. Assert.Empty(target.SelectedItems);
  200. Assert.Equal(1, raised);
  201. }
  202. [Fact]
  203. public void Changing_Source_To_Null_Raises_SelectedItems_PropertyChanged()
  204. {
  205. var target = CreateTarget();
  206. var selectedItemRaised = 0;
  207. var selectedItemsRaised = 0;
  208. target.Select(1);
  209. target.PropertyChanged += (s, e) =>
  210. {
  211. if (e.PropertyName == nameof(target.SelectedItem))
  212. {
  213. ++selectedItemRaised;
  214. }
  215. else if (e.PropertyName == nameof(target.SelectedItems))
  216. {
  217. ++selectedItemsRaised;
  218. }
  219. };
  220. target.Source = null;
  221. Assert.Equal(1, selectedItemRaised);
  222. Assert.Equal(1, selectedItemsRaised);
  223. }
  224. [Fact]
  225. public void Raises_PropertyChanged()
  226. {
  227. var target = CreateTarget();
  228. var raised = 0;
  229. target.PropertyChanged += (s, e) =>
  230. {
  231. if (e.PropertyName == nameof(target.Source))
  232. {
  233. ++raised;
  234. }
  235. };
  236. target.Source = new[] { "qux", "quux", "corge" };
  237. Assert.Equal(1, raised);
  238. }
  239. [Fact]
  240. public void Can_Assign_ValueType_Collection_To_SelectionModel_Of_Object()
  241. {
  242. var target = (ISelectionModel)new SelectionModel<object>();
  243. target.Source = new[] { 1, 2, 3 };
  244. }
  245. [Fact]
  246. public void Can_Change_Source_In_SelectedItem_Change_Handler()
  247. {
  248. // Issue #11617
  249. var target = CreateTarget();
  250. var raised = 0;
  251. target.PropertyChanged += (s, e) =>
  252. {
  253. if (e.PropertyName == nameof(target.SelectedItem) && raised == 0)
  254. {
  255. ++raised;
  256. target.Source = new[] { "foo", "baz", "bar" };
  257. }
  258. };
  259. target.SelectedIndex = 1;
  260. Assert.Equal(-1, target.SelectedIndex);
  261. }
  262. }
  263. public class SelectedIndex : ScopedTestBase
  264. {
  265. [Fact]
  266. public void SelectedIndex_Larger_Than_Source_Clears_Selection()
  267. {
  268. var target = CreateTarget();
  269. var raised = 0;
  270. target.SelectedIndex = 1;
  271. target.SelectionChanged += (s, e) =>
  272. {
  273. Assert.Equal(new[] { 1 }, e.DeselectedIndexes);
  274. Assert.Equal(new[] { "bar" }, e.DeselectedItems);
  275. Assert.Empty(e.SelectedIndexes);
  276. Assert.Empty(e.SelectedItems);
  277. ++raised;
  278. };
  279. target.SelectedIndex = 5;
  280. Assert.Equal(-1, target.SelectedIndex);
  281. Assert.Empty(target.SelectedIndexes);
  282. Assert.Null(target.SelectedItem);
  283. Assert.Empty(target.SelectedItems);
  284. Assert.Equal(1, raised);
  285. }
  286. [Fact]
  287. public void Negative_SelectedIndex_Is_Coerced_To_Minus_1()
  288. {
  289. var target = CreateTarget();
  290. var raised = 0;
  291. target.SelectionChanged += (s, e) => ++raised;
  292. target.SelectedIndex = -5;
  293. Assert.Equal(-1, target.SelectedIndex);
  294. Assert.Empty(target.SelectedIndexes);
  295. Assert.Null(target.SelectedItem);
  296. Assert.Empty(target.SelectedItems);
  297. Assert.Equal(0, raised);
  298. }
  299. [Fact]
  300. public void Setting_SelectedIndex_Clears_Old_Selection()
  301. {
  302. var target = CreateTarget();
  303. var raised = 0;
  304. target.SelectedIndex = 0;
  305. target.SelectionChanged += (s, e) =>
  306. {
  307. Assert.Equal(new[] { 0 }, e.DeselectedIndexes);
  308. Assert.Equal(new[] { "foo" }, e.DeselectedItems);
  309. Assert.Equal(new[] { 1 }, e.SelectedIndexes);
  310. Assert.Equal(new[] { "bar" }, e.SelectedItems);
  311. ++raised;
  312. };
  313. target.SelectedIndex = 1;
  314. Assert.Equal(1, target.SelectedIndex);
  315. Assert.Equal(new[] { 1 }, target.SelectedIndexes);
  316. Assert.Equal("bar", target.SelectedItem);
  317. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  318. Assert.Equal(1, raised);
  319. }
  320. [Fact]
  321. public void Setting_SelectedIndex_During_CollectionChanged_Results_In_Correct_Selection()
  322. {
  323. // Issue #4496
  324. var data = new AvaloniaList<string>();
  325. var target = CreateTarget();
  326. var binding = new MockBinding(target, data);
  327. target.Source = data;
  328. data.Add("foo");
  329. Assert.Equal(0, target.SelectedIndex);
  330. }
  331. [Fact]
  332. public void PropertyChanged_Is_Raised()
  333. {
  334. var target = CreateTarget();
  335. var raised = 0;
  336. target.PropertyChanged += (s, e) =>
  337. {
  338. if (e.PropertyName == nameof(target.SelectedIndex))
  339. {
  340. ++raised;
  341. }
  342. };
  343. target.SelectedIndex = 1;
  344. Assert.Equal(1, raised);
  345. }
  346. private class MockBinding : ICollectionChangedListener
  347. {
  348. private readonly SelectionModel<string?> _target;
  349. public MockBinding(SelectionModel<string?> target, AvaloniaList<string> data)
  350. {
  351. _target = target;
  352. CollectionChangedEventManager.Instance.AddListener(data, this);
  353. }
  354. public void Changed(INotifyCollectionChanged sender, NotifyCollectionChangedEventArgs e)
  355. {
  356. _target.Select(0);
  357. }
  358. public void PostChanged(INotifyCollectionChanged sender, NotifyCollectionChangedEventArgs e)
  359. {
  360. }
  361. public void PreChanged(INotifyCollectionChanged sender, NotifyCollectionChangedEventArgs e)
  362. {
  363. }
  364. }
  365. }
  366. public class SelectedItem : ScopedTestBase
  367. {
  368. [Fact]
  369. public void Setting_SelectedItem_To_Valid_Item_Updates_Selection()
  370. {
  371. var target = CreateTarget();
  372. var raised = 0;
  373. target.SelectionChanged += (s, e) =>
  374. {
  375. Assert.Empty(e.DeselectedIndexes);
  376. Assert.Empty(e.DeselectedItems);
  377. Assert.Equal(new[] { 1 }, e.SelectedIndexes);
  378. Assert.Equal(new[] { "bar" }, e.SelectedItems);
  379. ++raised;
  380. };
  381. target.SelectedItem = "bar";
  382. Assert.Equal(1, raised);
  383. }
  384. [Fact]
  385. public void PropertyChanged_Is_Raised_When_SelectedIndex_Changes()
  386. {
  387. var target = CreateTarget();
  388. var raised = 0;
  389. target.PropertyChanged += (s, e) =>
  390. {
  391. if (e.PropertyName == nameof(target.SelectedItem))
  392. {
  393. ++raised;
  394. }
  395. };
  396. target.SelectedIndex = 1;
  397. Assert.Equal(1, raised);
  398. }
  399. }
  400. public class SelectedIndexes : ScopedTestBase
  401. {
  402. [Fact]
  403. public void PropertyChanged_Is_Raised_When_SelectedIndex_Changes()
  404. {
  405. var target = CreateTarget();
  406. var raised = 0;
  407. target.PropertyChanged += (s, e) =>
  408. {
  409. if (e.PropertyName == nameof(target.SelectedIndexes))
  410. {
  411. ++raised;
  412. }
  413. };
  414. target.SelectedIndex = 1;
  415. Assert.Equal(1, raised);
  416. }
  417. [Fact]
  418. public void CollectionChanged_Is_Raised_When_SelectedIndex_Changes()
  419. {
  420. var target = CreateTarget();
  421. var raised = 0;
  422. var incc = Assert.IsAssignableFrom<INotifyCollectionChanged>(target.SelectedIndexes);
  423. incc.CollectionChanged += (s, e) =>
  424. {
  425. // For the moment, for simplicity, we raise a Reset event when the SelectedIndexes
  426. // collection changes - whatever the change. This can be improved later if necessary.
  427. Assert.Equal(NotifyCollectionChangedAction.Reset, e.Action);
  428. ++raised;
  429. };
  430. target.SelectedIndex = 1;
  431. Assert.Equal(1, raised);
  432. }
  433. }
  434. public class SelectedItems : ScopedTestBase
  435. {
  436. [Fact]
  437. public void PropertyChanged_Is_Raised_When_SelectedIndex_Changes()
  438. {
  439. var target = CreateTarget();
  440. var raised = 0;
  441. target.PropertyChanged += (s, e) =>
  442. {
  443. if (e.PropertyName == nameof(target.SelectedItems))
  444. {
  445. ++raised;
  446. }
  447. };
  448. target.SelectedIndex = 1;
  449. Assert.Equal(1, raised);
  450. }
  451. [Fact]
  452. public void CollectionChanged_Is_Raised_When_SelectedIndex_Changes()
  453. {
  454. var target = CreateTarget();
  455. var raised = 0;
  456. var incc = Assert.IsAssignableFrom<INotifyCollectionChanged>(target.SelectedIndexes);
  457. incc.CollectionChanged += (s, e) =>
  458. {
  459. // For the moment, for simplicity, we raise a Reset event when the SelectedItems
  460. // collection changes - whatever the change. This can be improved later if necessary.
  461. Assert.Equal(NotifyCollectionChangedAction.Reset, e.Action);
  462. ++raised;
  463. };
  464. target.SelectedIndex = 1;
  465. Assert.Equal(1, raised);
  466. }
  467. }
  468. public class Select : ScopedTestBase
  469. {
  470. [Fact]
  471. public void Select_Sets_SelectedIndex()
  472. {
  473. var target = CreateTarget();
  474. var raised = 0;
  475. target.SelectedIndex = 0;
  476. target.PropertyChanged += (s, e) =>
  477. {
  478. if (e.PropertyName == nameof(target.SelectedIndex))
  479. {
  480. ++raised;
  481. }
  482. };
  483. target.Select(1);
  484. Assert.Equal(1, target.SelectedIndex);
  485. Assert.Equal(1, raised);
  486. }
  487. [Fact]
  488. public void Select_Clears_Old_Selection()
  489. {
  490. var target = CreateTarget();
  491. var raised = 0;
  492. target.SelectedIndex = 0;
  493. target.SelectionChanged += (s, e) =>
  494. {
  495. Assert.Equal(new[] { 0 }, e.DeselectedIndexes);
  496. Assert.Equal(new[] { "foo" }, e.DeselectedItems);
  497. Assert.Equal(new[] { 1 }, e.SelectedIndexes);
  498. Assert.Equal(new[] { "bar" }, e.SelectedItems);
  499. ++raised;
  500. };
  501. target.Select(1);
  502. Assert.Equal(1, target.SelectedIndex);
  503. Assert.Equal(new[] { 1 }, target.SelectedIndexes);
  504. Assert.Equal("bar", target.SelectedItem);
  505. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  506. Assert.Equal(1, raised);
  507. }
  508. [Fact]
  509. public void Select_With_Invalid_Index_Does_Nothing()
  510. {
  511. var target = CreateTarget();
  512. var raised = 0;
  513. target.SelectedIndex = 0;
  514. target.PropertyChanged += (s, e) => ++raised;
  515. target.SelectionChanged += (s, e) => ++raised;
  516. target.Select(5);
  517. Assert.Equal(0, target.SelectedIndex);
  518. Assert.Equal(new[] { 0 }, target.SelectedIndexes);
  519. Assert.Equal("foo", target.SelectedItem);
  520. Assert.Equal(new[] { "foo" }, target.SelectedItems);
  521. Assert.Equal(0, raised);
  522. }
  523. [Fact]
  524. public void Selecting_Already_Selected_Item_Doesnt_Raise_SelectionChanged()
  525. {
  526. var target = CreateTarget();
  527. var raised = 0;
  528. target.Select(2);
  529. target.SelectionChanged += (s, e) => ++raised;
  530. target.Select(2);
  531. Assert.Equal(0, raised);
  532. }
  533. }
  534. public class SelectRange : ScopedTestBase
  535. {
  536. [Fact]
  537. public void SelectRange_Throws()
  538. {
  539. var target = CreateTarget();
  540. Assert.Throws<InvalidOperationException>(() => target.SelectRange(0, 10));
  541. }
  542. }
  543. public class Deselect : ScopedTestBase
  544. {
  545. [Fact]
  546. public void Deselect_Clears_Current_Selection()
  547. {
  548. var target = CreateTarget();
  549. var raised = 0;
  550. target.SelectedIndex = 0;
  551. target.SelectionChanged += (s, e) =>
  552. {
  553. Assert.Equal(new[] { 0 }, e.DeselectedIndexes);
  554. Assert.Equal(new[] { "foo" }, e.DeselectedItems);
  555. Assert.Empty(e.SelectedIndexes);
  556. Assert.Empty(e.SelectedItems);
  557. ++raised;
  558. };
  559. target.Deselect(0);
  560. Assert.Equal(-1, target.SelectedIndex);
  561. Assert.Empty(target.SelectedIndexes);
  562. Assert.Null(target.SelectedItem);
  563. Assert.Empty(target.SelectedItems);
  564. Assert.Equal(1, raised);
  565. }
  566. [Fact]
  567. public void Deselect_Does_Nothing_For_Nonselected_Item()
  568. {
  569. var target = CreateTarget();
  570. var raised = 0;
  571. target.SelectedIndex = 1;
  572. target.SelectionChanged += (s, e) => ++raised;
  573. target.Deselect(0);
  574. Assert.Equal(1, target.SelectedIndex);
  575. Assert.Equal(new[] { 1 }, target.SelectedIndexes);
  576. Assert.Equal("bar", target.SelectedItem);
  577. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  578. Assert.Equal(0, raised);
  579. }
  580. }
  581. public class DeselectRange : ScopedTestBase
  582. {
  583. [Fact]
  584. public void DeselectRange_Clears_Current_Selection_For_Intersecting_Range()
  585. {
  586. var target = CreateTarget();
  587. var raised = 0;
  588. target.SelectedIndex = 0;
  589. target.SelectionChanged += (s, e) =>
  590. {
  591. Assert.Equal(new[] { 0 }, e.DeselectedIndexes);
  592. Assert.Equal(new[] { "foo" }, e.DeselectedItems);
  593. Assert.Empty(e.SelectedIndexes);
  594. Assert.Empty(e.SelectedItems);
  595. ++raised;
  596. };
  597. target.DeselectRange(0, 2);
  598. Assert.Equal(-1, target.SelectedIndex);
  599. Assert.Empty(target.SelectedIndexes);
  600. Assert.Null(target.SelectedItem);
  601. Assert.Empty(target.SelectedItems);
  602. Assert.Equal(1, raised);
  603. }
  604. [Fact]
  605. public void DeselectRange_Does_Nothing_For_Nonintersecting_Range()
  606. {
  607. var target = CreateTarget();
  608. var raised = 0;
  609. target.SelectedIndex = 0;
  610. target.SelectionChanged += (s, e) => ++raised;
  611. target.DeselectRange(1, 2);
  612. Assert.Equal(0, target.SelectedIndex);
  613. Assert.Equal(new[] { 0 }, target.SelectedIndexes);
  614. Assert.Equal("foo", target.SelectedItem);
  615. Assert.Equal(new[] { "foo" }, target.SelectedItems);
  616. Assert.Equal(0, raised);
  617. }
  618. }
  619. public class Clear : ScopedTestBase
  620. {
  621. [Fact]
  622. public void Clear_Raises_SelectionChanged()
  623. {
  624. var target = CreateTarget();
  625. var raised = 0;
  626. target.Select(1);
  627. target.SelectionChanged += (s, e) =>
  628. {
  629. Assert.Equal(new[] { 1 }, e.DeselectedIndexes);
  630. Assert.Equal(new[] { "bar" }, e.DeselectedItems);
  631. Assert.Empty(e.SelectedIndexes);
  632. Assert.Empty(e.SelectedItems);
  633. ++raised;
  634. };
  635. target.Clear();
  636. Assert.Equal(1, raised);
  637. }
  638. }
  639. public class AnchorIndex : ScopedTestBase
  640. {
  641. [Fact]
  642. public void Setting_SelectedIndex_Sets_AnchorIndex()
  643. {
  644. var target = CreateTarget();
  645. var raised = 0;
  646. target.PropertyChanged += (s, e) =>
  647. {
  648. if (e.PropertyName == nameof(target.AnchorIndex))
  649. {
  650. ++raised;
  651. }
  652. };
  653. target.SelectedIndex = 1;
  654. Assert.Equal(1, target.AnchorIndex);
  655. Assert.Equal(1, raised);
  656. }
  657. [Fact]
  658. public void Setting_SelectedIndex_To_Minus_1_Doesnt_Clear_AnchorIndex()
  659. {
  660. var target = CreateTarget();
  661. var raised = 0;
  662. target.SelectedIndex = 1;
  663. target.PropertyChanged += (s, e) =>
  664. {
  665. if (e.PropertyName == nameof(target.AnchorIndex))
  666. {
  667. ++raised;
  668. }
  669. };
  670. target.SelectedIndex = -1;
  671. Assert.Equal(1, target.AnchorIndex);
  672. Assert.Equal(0, raised);
  673. }
  674. [Fact]
  675. public void Select_Sets_AnchorIndex()
  676. {
  677. var target = CreateTarget();
  678. var raised = 0;
  679. target.PropertyChanged += (s, e) =>
  680. {
  681. if (e.PropertyName == nameof(target.AnchorIndex))
  682. {
  683. ++raised;
  684. }
  685. };
  686. target.Select(1);
  687. Assert.Equal(1, target.AnchorIndex);
  688. Assert.Equal(1, raised);
  689. }
  690. [Fact]
  691. public void Deselect_Doesnt_Clear_AnchorIndex()
  692. {
  693. var target = CreateTarget();
  694. var raised = 0;
  695. target.Select(1);
  696. target.PropertyChanged += (s, e) =>
  697. {
  698. if (e.PropertyName == nameof(target.AnchorIndex))
  699. {
  700. ++raised;
  701. }
  702. };
  703. target.Deselect(1);
  704. Assert.Equal(1, target.AnchorIndex);
  705. Assert.Equal(0, raised);
  706. }
  707. [Fact]
  708. public void Raises_PropertyChanged()
  709. {
  710. var target = CreateTarget();
  711. var raised = 0;
  712. target.PropertyChanged += (s, e) =>
  713. {
  714. if (e.PropertyName == nameof(target.AnchorIndex))
  715. {
  716. ++raised;
  717. }
  718. };
  719. target.SelectedIndex = 1;
  720. Assert.Equal(1, raised);
  721. }
  722. }
  723. public class SingleSelect : ScopedTestBase
  724. {
  725. [Fact]
  726. public void Converting_To_Multiple_Selection_Preserves_Selection()
  727. {
  728. var target = CreateTarget();
  729. var raised = 0;
  730. target.SelectedIndex = 1;
  731. target.SelectionChanged += (s, e) => ++raised;
  732. target.SingleSelect = false;
  733. Assert.Equal(1, target.SelectedIndex);
  734. Assert.Equal(new[] { 1 }, target.SelectedIndexes);
  735. Assert.Equal("bar", target.SelectedItem);
  736. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  737. Assert.Equal(0, raised);
  738. }
  739. [Fact]
  740. public void Raises_PropertyChanged()
  741. {
  742. var target = CreateTarget();
  743. var raised = 0;
  744. target.PropertyChanged += (s, e) =>
  745. {
  746. if (e.PropertyName == nameof(target.SingleSelect))
  747. {
  748. ++raised;
  749. }
  750. };
  751. target.SingleSelect = false;
  752. Assert.Equal(1, raised);
  753. }
  754. }
  755. public class CollectionChanges : ScopedTestBase
  756. {
  757. [Fact]
  758. public void Adding_Item_Before_Selected_Item_Updates_Indexes()
  759. {
  760. var target = CreateTarget();
  761. var data = (AvaloniaList<string>)target.Source!;
  762. var selectionChangedRaised = 0;
  763. var indexesChangedRaised = 0;
  764. var selectedIndexRaised = 0;
  765. target.SelectedIndex = 1;
  766. target.SelectionChanged += (s, e) => ++selectionChangedRaised;
  767. target.PropertyChanged += (s, e) =>
  768. {
  769. if (e.PropertyName == nameof(target.SelectedIndex))
  770. {
  771. ++selectedIndexRaised;
  772. }
  773. };
  774. target.IndexesChanged += (s, e) =>
  775. {
  776. Assert.Equal(0, e.StartIndex);
  777. Assert.Equal(1, e.Delta);
  778. ++indexesChangedRaised;
  779. };
  780. data.Insert(0, "new");
  781. Assert.Equal(2, target.SelectedIndex);
  782. Assert.Equal(new[] { 2 }, target.SelectedIndexes);
  783. Assert.Equal("bar", target.SelectedItem);
  784. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  785. Assert.Equal(2, target.AnchorIndex);
  786. Assert.Equal(1, indexesChangedRaised);
  787. Assert.Equal(1, selectedIndexRaised);
  788. Assert.Equal(0, selectionChangedRaised);
  789. }
  790. [Fact]
  791. public void Adding_Item_After_Selected_Doesnt_Raise_Events()
  792. {
  793. var target = CreateTarget();
  794. var data = (AvaloniaList<string>)target.Source!;
  795. var raised = 0;
  796. target.SelectedIndex = 1;
  797. target.PropertyChanged += (s, e) => ++raised;
  798. target.SelectionChanged += (s, e) => ++raised;
  799. target.IndexesChanged += (s, e) => ++raised;
  800. data.Insert(2, "new");
  801. Assert.Equal(1, target.SelectedIndex);
  802. Assert.Equal(new[] { 1 }, target.SelectedIndexes);
  803. Assert.Equal("bar", target.SelectedItem);
  804. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  805. Assert.Equal(1, target.AnchorIndex);
  806. Assert.Equal(0, raised);
  807. }
  808. [Fact]
  809. public void Removing_Selected_Item_Updates_State()
  810. {
  811. var target = CreateTarget();
  812. var data = (AvaloniaList<string>)target.Source!;
  813. var selectionChangedRaised = 0;
  814. var selectedIndexRaised = 0;
  815. target.Source = data;
  816. target.Select(1);
  817. target.PropertyChanged += (s, e) =>
  818. {
  819. if (e.PropertyName == nameof(target.SelectedIndex))
  820. {
  821. ++selectedIndexRaised;
  822. }
  823. };
  824. target.SelectionChanged += (s, e) =>
  825. {
  826. Assert.Empty(e.DeselectedIndexes);
  827. Assert.Equal(new[] { "bar" }, e.DeselectedItems);
  828. Assert.Empty(e.SelectedIndexes);
  829. Assert.Empty(e.SelectedItems);
  830. ++selectionChangedRaised;
  831. };
  832. data.RemoveAt(1);
  833. Assert.Equal(-1, target.SelectedIndex);
  834. Assert.Empty(target.SelectedIndexes);
  835. Assert.Null(target.SelectedItem);
  836. Assert.Empty(target.SelectedItems);
  837. Assert.Equal(-1, target.AnchorIndex);
  838. Assert.Equal(1, selectionChangedRaised);
  839. Assert.Equal(1, selectedIndexRaised);
  840. }
  841. [Fact]
  842. public void Removing_Item_Before_Selected_Item_Updates_Indexes()
  843. {
  844. var target = CreateTarget();
  845. var data = (AvaloniaList<string>)target.Source!;
  846. var selectionChangedRaised = 0;
  847. var indexesChangedraised = 0;
  848. target.SelectedIndex = 1;
  849. target.SelectionChanged += (s, e) => ++selectionChangedRaised;
  850. target.IndexesChanged += (s, e) =>
  851. {
  852. Assert.Equal(0, e.StartIndex);
  853. Assert.Equal(-1, e.Delta);
  854. ++indexesChangedraised;
  855. };
  856. data.RemoveAt(0);
  857. Assert.Equal(0, target.SelectedIndex);
  858. Assert.Equal(new[] { 0 }, target.SelectedIndexes);
  859. Assert.Equal("bar", target.SelectedItem);
  860. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  861. Assert.Equal(0, target.AnchorIndex);
  862. Assert.Equal(1, indexesChangedraised);
  863. Assert.Equal(0, selectionChangedRaised);
  864. }
  865. [Fact]
  866. public void Removing_Item_After_Selected_Doesnt_Raise_Events()
  867. {
  868. var target = CreateTarget();
  869. var data = (AvaloniaList<string>)target.Source!;
  870. var raised = 0;
  871. target.SelectedIndex = 1;
  872. target.PropertyChanged += (s, e) => ++raised;
  873. target.SelectionChanged += (s, e) => ++raised;
  874. target.IndexesChanged += (s, e) => ++raised;
  875. data.RemoveAt(2);
  876. Assert.Equal(1, target.SelectedIndex);
  877. Assert.Equal(new[] { 1 }, target.SelectedIndexes);
  878. Assert.Equal("bar", target.SelectedItem);
  879. Assert.Equal(new[] { "bar" }, target.SelectedItems);
  880. Assert.Equal(1, target.AnchorIndex);
  881. Assert.Equal(0, raised);
  882. }
  883. [Fact]
  884. public void Replacing_Selected_Item_Updates_State()
  885. {
  886. var target = CreateTarget();
  887. var data = (AvaloniaList<string>)target.Source!;
  888. var selectionChangedRaised = 0;
  889. var selectedIndexRaised = 0;
  890. var selectedItemRaised = 0;
  891. target.Source = data;
  892. target.Select(1);
  893. target.PropertyChanged += (s, e) =>
  894. {
  895. if (e.PropertyName == nameof(target.SelectedIndex))
  896. {
  897. ++selectedIndexRaised;
  898. }
  899. if (e.PropertyName == nameof(target.SelectedItem))
  900. {
  901. ++selectedItemRaised;
  902. }
  903. };
  904. target.SelectionChanged += (s, e) =>
  905. {
  906. Assert.Empty(e.DeselectedIndexes);
  907. Assert.Equal(new[] { "bar" }, e.DeselectedItems);
  908. Assert.Empty(e.SelectedIndexes);
  909. Assert.Empty(e.SelectedItems);
  910. ++selectionChangedRaised;
  911. };
  912. data[1] = "new";
  913. Assert.Equal(-1, target.SelectedIndex);
  914. Assert.Empty(target.SelectedIndexes);
  915. Assert.Null(target.SelectedItem);
  916. Assert.Empty(target.SelectedItems);
  917. Assert.Equal(-1, target.AnchorIndex);
  918. Assert.Equal(1, selectionChangedRaised);
  919. Assert.Equal(1, selectedIndexRaised);
  920. Assert.Equal(1, selectedItemRaised);
  921. }
  922. [Fact]
  923. public void Moving_Selected_Item_Updates_State()
  924. {
  925. var target = CreateTarget();
  926. var data = (AvaloniaList<string>)target.Source!;
  927. var selectionChangedRaised = 0;
  928. var selectedIndexRaised = 0;
  929. var selectedItemRaised = 0;
  930. target.Source = data;
  931. target.Select(1);
  932. target.PropertyChanged += (s, e) =>
  933. {
  934. if (e.PropertyName == nameof(target.SelectedIndex))
  935. {
  936. ++selectedIndexRaised;
  937. }
  938. if (e.PropertyName == nameof(target.SelectedItem))
  939. {
  940. ++selectedItemRaised;
  941. }
  942. };
  943. target.SelectionChanged += (s, e) =>
  944. {
  945. Assert.Empty(e.DeselectedIndexes);
  946. Assert.Equal(new[] { "bar" }, e.DeselectedItems);
  947. Assert.Empty(e.SelectedIndexes);
  948. Assert.Empty(e.SelectedItems);
  949. ++selectionChangedRaised;
  950. };
  951. data.Move(1, 0);
  952. Assert.Equal(-1, target.SelectedIndex);
  953. Assert.Empty(target.SelectedIndexes);
  954. Assert.Null(target.SelectedItem);
  955. Assert.Empty(target.SelectedItems);
  956. Assert.Equal(-1, target.AnchorIndex);
  957. Assert.Equal(1, selectionChangedRaised);
  958. Assert.Equal(1, selectedIndexRaised);
  959. Assert.Equal(1, selectedItemRaised);
  960. }
  961. [Fact]
  962. public void Resetting_Source_Updates_State()
  963. {
  964. var target = CreateTarget();
  965. var data = (AvaloniaList<string>)target.Source!;
  966. var selectionChangedRaised = 0;
  967. var selectedIndexRaised = 0;
  968. var resetRaised = 0;
  969. target.Source = data;
  970. target.Select(1);
  971. target.PropertyChanged += (s, e) =>
  972. {
  973. if (e.PropertyName == nameof(target.SelectedIndex))
  974. {
  975. ++selectedIndexRaised;
  976. }
  977. };
  978. target.SelectionChanged += (s, e) => ++selectionChangedRaised;
  979. target.SourceReset += (s, e) => ++resetRaised;
  980. data.Clear();
  981. Assert.Equal(-1, target.SelectedIndex);
  982. Assert.Empty(target.SelectedIndexes);
  983. Assert.Null(target.SelectedItem);
  984. Assert.Empty(target.SelectedItems);
  985. Assert.Equal(-1, target.AnchorIndex);
  986. Assert.Equal(0, selectionChangedRaised);
  987. Assert.Equal(1, resetRaised);
  988. Assert.Equal(1, selectedIndexRaised);
  989. }
  990. [Fact]
  991. public void Handles_Selection_Made_In_CollectionChanged()
  992. {
  993. // Tests the following scenario:
  994. //
  995. // - Items changes from empty to having 1 item
  996. // - ViewModel auto-selects item 0 in CollectionChanged
  997. // - SelectionModel receives CollectionChanged
  998. // - And so adjusts the selected item from 0 to 1, which is past the end of the items.
  999. //
  1000. // There's not much we can do about this situation because the order in which
  1001. // CollectionChanged handlers are called can't be known (the problem also exists with
  1002. // WPF). The best we can do is not select an invalid index.
  1003. var target = CreateTarget(createData: false);
  1004. var data = new AvaloniaList<string>();
  1005. data.CollectionChanged += (s, e) =>
  1006. {
  1007. target.Select(0);
  1008. };
  1009. target.Source = data;
  1010. data.Add("foo");
  1011. Assert.Equal(0, target.SelectedIndex);
  1012. Assert.Equal(new[] { 0 }, target.SelectedIndexes);
  1013. Assert.Equal("foo", target.SelectedItem);
  1014. Assert.Equal(new[] { "foo" }, target.SelectedItems);
  1015. Assert.Equal(0, target.AnchorIndex);
  1016. }
  1017. [Fact]
  1018. public void SelectedItems_Indexer_Is_Correct()
  1019. {
  1020. // Issue #7974
  1021. var target = CreateTarget();
  1022. var raised = 0;
  1023. target.SelectionChanged += (s, e) =>
  1024. {
  1025. Assert.Equal("bar", e.SelectedItems.First());
  1026. Assert.Equal("bar", e.SelectedItems[0]);
  1027. ++raised;
  1028. };
  1029. target.Select(1);
  1030. Assert.Equal(1, raised);
  1031. }
  1032. }
  1033. public class BatchUpdate : ScopedTestBase
  1034. {
  1035. [Fact]
  1036. public void Changes_Do_Not_Take_Effect_Until_EndUpdate_Called()
  1037. {
  1038. var target = CreateTarget();
  1039. target.BeginBatchUpdate();
  1040. target.Select(0);
  1041. Assert.Equal(-1, target.SelectedIndex);
  1042. target.EndBatchUpdate();
  1043. Assert.Equal(0, target.SelectedIndex);
  1044. }
  1045. [Fact]
  1046. public void Correctly_Batches_Clear_SelectedIndex()
  1047. {
  1048. var target = CreateTarget();
  1049. var raised = 0;
  1050. target.SelectedIndex = 2;
  1051. target.SelectionChanged += (s, e) => ++raised;
  1052. using (target.BatchUpdate())
  1053. {
  1054. target.Clear();
  1055. target.SelectedIndex = 2;
  1056. }
  1057. Assert.Equal(0, raised);
  1058. }
  1059. }
  1060. public class LostSelection : ScopedTestBase
  1061. {
  1062. [Fact]
  1063. public void LostSelection_Called_On_Clear()
  1064. {
  1065. var target = CreateTarget();
  1066. var raised = 0;
  1067. target.SelectedIndex = 1;
  1068. target.SelectionChanged += (s, e) =>
  1069. {
  1070. Assert.Equal(new[] { 1 }, e.DeselectedIndexes);
  1071. Assert.Equal(new[] { "bar" }, e.DeselectedItems);
  1072. Assert.Equal(new[] { 0 }, e.SelectedIndexes);
  1073. Assert.Equal(new[] { "foo" }, e.SelectedItems);
  1074. ++raised;
  1075. };
  1076. target.LostSelection += (s, e) =>
  1077. {
  1078. target.Select(0);
  1079. };
  1080. target.Clear();
  1081. Assert.Equal(0, target.SelectedIndex);
  1082. Assert.Equal(1, raised);
  1083. }
  1084. [Fact]
  1085. public void LostSelection_Called_When_SelectedItem_Removed()
  1086. {
  1087. var target = CreateTarget();
  1088. var data = (AvaloniaList<string>)target.Source!;
  1089. var raised = 0;
  1090. target.SelectedIndex = 1;
  1091. target.SelectionChanged += (s, e) =>
  1092. {
  1093. Assert.Empty(e.DeselectedIndexes);
  1094. Assert.Equal(new[] { "bar" }, e.DeselectedItems);
  1095. Assert.Equal(new[] { 0 }, e.SelectedIndexes);
  1096. Assert.Equal(new[] { "foo" }, e.SelectedItems);
  1097. ++raised;
  1098. };
  1099. target.LostSelection += (s, e) =>
  1100. {
  1101. target.Select(0);
  1102. };
  1103. data.RemoveAt(1);
  1104. Assert.Equal(0, target.SelectedIndex);
  1105. Assert.Equal(1, raised);
  1106. }
  1107. [Fact]
  1108. public void LostSelection_Not_Called_With_Old_Source_When_Changing_Source()
  1109. {
  1110. var target = CreateTarget();
  1111. var data = (AvaloniaList<string>)target.Source!;
  1112. var raised = 0;
  1113. target.LostSelection += (s, e) =>
  1114. {
  1115. if (target.Source == data)
  1116. {
  1117. ++raised;
  1118. }
  1119. };
  1120. target.Source = null;
  1121. Assert.Equal(0, raised);
  1122. }
  1123. [Fact]
  1124. public void LostSelection_Is_Called_When_Source_Changed_While_CollectionChange_In_Progress()
  1125. {
  1126. // Issue #12733.
  1127. var data1 = new AvaloniaList<string> { "foo1", "bar1", "baz1" };
  1128. var data2 = new AvaloniaList<string> { "foo1", "bar1", "baz1" };
  1129. var target = new DerivedSelectionModel { Source = data1 };
  1130. var raised = 0;
  1131. target.LostSelection += (s, e) =>
  1132. {
  1133. if (target.Source == data2)
  1134. {
  1135. ++raised;
  1136. }
  1137. };
  1138. target.UpdateSource(data2);
  1139. Assert.Equal(1, raised);
  1140. }
  1141. private class DerivedSelectionModel : SelectionModel<string?>
  1142. {
  1143. public void UpdateSource(IEnumerable? source)
  1144. {
  1145. OnSourceCollectionChangeStarted();
  1146. Source = source;
  1147. OnSourceCollectionChangeFinished();
  1148. }
  1149. }
  1150. }
  1151. public class UntypedInterface : ScopedTestBase
  1152. {
  1153. [Fact]
  1154. public void Raises_Untyped_SelectionChanged_Event()
  1155. {
  1156. var target = CreateTarget();
  1157. var raised = 0;
  1158. target.SelectedIndex = 1;
  1159. ((ISelectionModel)target).SelectionChanged += (s, e) =>
  1160. {
  1161. Assert.Equal(new[] { 1 }, e.DeselectedIndexes);
  1162. Assert.Equal(new[] { "bar" }, e.DeselectedItems);
  1163. Assert.Equal(new[] { 2 }, e.SelectedIndexes);
  1164. Assert.Equal(new[] { "baz" }, e.SelectedItems);
  1165. ++raised;
  1166. };
  1167. target.SelectedIndex = 2;
  1168. Assert.Equal(1, raised);
  1169. }
  1170. }
  1171. private static SelectionModel<string?> CreateTarget(bool createData = true)
  1172. {
  1173. var result = new SelectionModel<string?> { SingleSelect = true };
  1174. if (createData)
  1175. {
  1176. result.Source = new AvaloniaList<string> { "foo", "bar", "baz" };
  1177. }
  1178. return result;
  1179. }
  1180. }
  1181. }