ItemsPresenterTests_Virtualization.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using Avalonia.Controls.Generators;
  6. using Avalonia.Controls.Presenters;
  7. using Avalonia.Controls.Primitives;
  8. using Avalonia.Controls.Templates;
  9. using Xunit;
  10. namespace Avalonia.Controls.UnitTests.Presenters
  11. {
  12. public class ItemsPresenterTests_Virtualization
  13. {
  14. [Fact]
  15. public void Should_Return_IsLogicalScrollEnabled_False_When_Has_No_Virtualizing_Panel()
  16. {
  17. var target = CreateTarget();
  18. target.ClearValue(ItemsPresenter.ItemsPanelProperty);
  19. target.ApplyTemplate();
  20. Assert.False(((ILogicalScrollable)target).IsLogicalScrollEnabled);
  21. }
  22. [Fact]
  23. public void Should_Return_IsLogicalScrollEnabled_False_When_VirtualizationMode_None()
  24. {
  25. var target = CreateTarget(ItemVirtualizationMode.None);
  26. target.ApplyTemplate();
  27. Assert.False(((ILogicalScrollable)target).IsLogicalScrollEnabled);
  28. }
  29. [Fact]
  30. public void Should_Return_IsLogicalScrollEnabled_False_When_Doesnt_Have_ScrollPresenter_Parent()
  31. {
  32. var target = new ItemsPresenter
  33. {
  34. ItemsPanel = VirtualizingPanelTemplate(),
  35. ItemTemplate = ItemTemplate(),
  36. VirtualizationMode = ItemVirtualizationMode.Simple,
  37. };
  38. target.ApplyTemplate();
  39. Assert.False(((ILogicalScrollable)target).IsLogicalScrollEnabled);
  40. }
  41. [Fact]
  42. public void Should_Return_IsLogicalScrollEnabled_True()
  43. {
  44. var target = CreateTarget();
  45. target.ApplyTemplate();
  46. Assert.True(((ILogicalScrollable)target).IsLogicalScrollEnabled);
  47. }
  48. [Fact]
  49. public void Parent_ScrollContentPresenter_Properties_Should_Be_Set()
  50. {
  51. var target = CreateTarget();
  52. target.ApplyTemplate();
  53. target.Measure(new Size(100, 100));
  54. target.Arrange(new Rect(0, 0, 100, 100));
  55. var scroll = (ScrollContentPresenter)target.Parent;
  56. Assert.Equal(new Size(0, 20), scroll.Extent);
  57. Assert.Equal(new Size(0, 10), scroll.Viewport);
  58. }
  59. [Fact]
  60. public void Should_Fill_Panel_With_Containers()
  61. {
  62. var target = CreateTarget();
  63. target.ApplyTemplate();
  64. target.Measure(new Size(100, 100));
  65. Assert.Equal(10, target.Panel.Children.Count);
  66. target.Arrange(new Rect(0, 0, 100, 100));
  67. Assert.Equal(10, target.Panel.Children.Count);
  68. }
  69. [Fact]
  70. public void Should_Only_Create_Enough_Containers_To_Display_All_Items()
  71. {
  72. var target = CreateTarget(itemCount: 2);
  73. target.ApplyTemplate();
  74. target.Measure(new Size(100, 100));
  75. target.Arrange(new Rect(0, 0, 100, 100));
  76. Assert.Equal(2, target.Panel.Children.Count);
  77. }
  78. [Fact]
  79. public void Should_Expand_To_Fit_Containers_When_Flexible_Size()
  80. {
  81. var target = CreateTarget();
  82. target.ApplyTemplate();
  83. target.Measure(Size.Infinity);
  84. target.Arrange(new Rect(target.DesiredSize));
  85. Assert.Equal(new Size(10, 200), target.DesiredSize);
  86. Assert.Equal(new Size(10, 200), target.Bounds.Size);
  87. Assert.Equal(20, target.Panel.Children.Count);
  88. }
  89. [Fact]
  90. public void Initial_Item_DataContexts_Should_Be_Correct()
  91. {
  92. var target = CreateTarget();
  93. var items = (IList<string>)target.Items;
  94. target.ApplyTemplate();
  95. target.Measure(new Size(100, 100));
  96. target.Arrange(new Rect(0, 0, 100, 100));
  97. for (var i = 0; i < target.Panel.Children.Count; ++i)
  98. {
  99. Assert.Equal(items[i], target.Panel.Children[i].DataContext);
  100. }
  101. }
  102. [Fact]
  103. public void Should_Add_New_Items_When_Control_Is_Enlarged()
  104. {
  105. var target = CreateTarget();
  106. var items = (IList<string>)target.Items;
  107. target.ApplyTemplate();
  108. target.Measure(new Size(100, 100));
  109. target.Arrange(new Rect(0, 0, 100, 100));
  110. Assert.Equal(10, target.Panel.Children.Count);
  111. target.Measure(new Size(120, 120));
  112. target.Arrange(new Rect(0, 0, 100, 120));
  113. Assert.Equal(12, target.Panel.Children.Count);
  114. for (var i = 0; i < target.Panel.Children.Count; ++i)
  115. {
  116. Assert.Equal(items[i], target.Panel.Children[i].DataContext);
  117. }
  118. }
  119. [Fact]
  120. public void Changing_VirtualizationMode_None_To_Simple_Should_Update_Control()
  121. {
  122. var target = CreateTarget(mode: ItemVirtualizationMode.None);
  123. var scroll = (ScrollContentPresenter)target.Parent;
  124. target.ApplyTemplate();
  125. scroll.Measure(new Size(100, 100));
  126. scroll.Arrange(new Rect(0, 0, 100, 100));
  127. Assert.Equal(20, target.Panel.Children.Count);
  128. Assert.Equal(new Size(10, 200), scroll.Extent);
  129. Assert.Equal(new Size(100, 100), scroll.Viewport);
  130. target.VirtualizationMode = ItemVirtualizationMode.Simple;
  131. scroll.Measure(new Size(100, 100));
  132. scroll.Arrange(new Rect(0, 0, 100, 100));
  133. Assert.Equal(10, target.Panel.Children.Count);
  134. Assert.Equal(new Size(0, 20), scroll.Extent);
  135. Assert.Equal(new Size(0, 10), scroll.Viewport);
  136. }
  137. [Fact]
  138. public void Changing_VirtualizationMode_Simple_To_None_Should_Update_Control()
  139. {
  140. var target = CreateTarget();
  141. target.ApplyTemplate();
  142. target.Measure(new Size(100, 100));
  143. target.Arrange(new Rect(0, 0, 100, 100));
  144. var scroll = (ScrollContentPresenter)target.Parent;
  145. Assert.Equal(10, target.Panel.Children.Count);
  146. Assert.Equal(new Size(0, 20), scroll.Extent);
  147. Assert.Equal(new Size(0, 10), scroll.Viewport);
  148. target.VirtualizationMode = ItemVirtualizationMode.None;
  149. scroll.Measure(new Size(100, 100));
  150. scroll.Arrange(new Rect(0, 0, 100, 100));
  151. Assert.Equal(20, target.Panel.Children.Count);
  152. Assert.Equal(new Size(10, 200), scroll.Extent);
  153. Assert.Equal(new Size(100, 100), scroll.Viewport);
  154. }
  155. private static ItemsPresenter CreateTarget(
  156. ItemVirtualizationMode mode = ItemVirtualizationMode.Simple,
  157. Orientation orientation = Orientation.Vertical,
  158. bool useContainers = true,
  159. int itemCount = 20)
  160. {
  161. ItemsPresenter result;
  162. var items = Enumerable.Range(0, itemCount).Select(x => $"Item {x}").ToList();
  163. var scroller = new ScrollContentPresenter
  164. {
  165. Content = result = new TestItemsPresenter(useContainers)
  166. {
  167. Items = items,
  168. ItemsPanel = VirtualizingPanelTemplate(orientation),
  169. ItemTemplate = ItemTemplate(),
  170. VirtualizationMode = mode,
  171. }
  172. };
  173. scroller.UpdateChild();
  174. return result;
  175. }
  176. private static IDataTemplate ItemTemplate()
  177. {
  178. return new FuncDataTemplate<string>(x => new Canvas
  179. {
  180. Width = 10,
  181. Height = 10,
  182. });
  183. }
  184. private static ITemplate<IPanel> VirtualizingPanelTemplate(
  185. Orientation orientation = Orientation.Vertical)
  186. {
  187. return new FuncTemplate<IPanel>(() => new VirtualizingStackPanel
  188. {
  189. Orientation = orientation,
  190. });
  191. }
  192. private class TestItemsPresenter : ItemsPresenter
  193. {
  194. private bool _useContainers;
  195. public TestItemsPresenter(bool useContainers)
  196. {
  197. _useContainers = useContainers;
  198. }
  199. protected override IItemContainerGenerator CreateItemContainerGenerator()
  200. {
  201. return _useContainers ?
  202. new ItemContainerGenerator<TestContainer>(this, TestContainer.ContentProperty, null) :
  203. new ItemContainerGenerator(this);
  204. }
  205. }
  206. private class TestContainer : ContentControl
  207. {
  208. public TestContainer()
  209. {
  210. Width = 10;
  211. Height = 10;
  212. }
  213. }
  214. }
  215. }