ItemsPresenterTests_Virtualization.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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.Presenters;
  6. using Avalonia.Controls.Primitives;
  7. using Avalonia.Controls.Templates;
  8. using Xunit;
  9. namespace Avalonia.Controls.UnitTests.Presenters
  10. {
  11. public class ItemsPresenterTests_Virtualization
  12. {
  13. [Fact]
  14. public void Should_Return_IsLogicalScrollEnabled_False_When_Has_No_Virtualizing_Panel()
  15. {
  16. var target = CreateTarget();
  17. target.ClearValue(ItemsPresenter.ItemsPanelProperty);
  18. target.ApplyTemplate();
  19. Assert.False(((IScrollable)target).IsLogicalScrollEnabled);
  20. }
  21. [Fact]
  22. public void Should_Return_IsLogicalScrollEnabled_False_When_VirtualizationMode_None()
  23. {
  24. var target = CreateTarget(ItemVirtualizationMode.None);
  25. target.ApplyTemplate();
  26. Assert.False(((IScrollable)target).IsLogicalScrollEnabled);
  27. }
  28. [Fact]
  29. public void Should_Return_IsLogicalScrollEnabled_False_When_Doesnt_Have_ScrollPresenter_Parent()
  30. {
  31. var target = new ItemsPresenter
  32. {
  33. ItemsPanel = VirtualizingPanelTemplate(),
  34. ItemTemplate = ItemTemplate(),
  35. VirtualizationMode = ItemVirtualizationMode.Simple,
  36. };
  37. target.ApplyTemplate();
  38. Assert.False(((IScrollable)target).IsLogicalScrollEnabled);
  39. }
  40. [Fact]
  41. public void Should_Return_IsLogicalScrollEnabled_True()
  42. {
  43. var target = CreateTarget();
  44. target.ApplyTemplate();
  45. Assert.True(((IScrollable)target).IsLogicalScrollEnabled);
  46. }
  47. [Fact]
  48. public void Should_Fill_Panel_With_Containers()
  49. {
  50. var target = CreateTarget();
  51. target.ApplyTemplate();
  52. target.Measure(new Size(100, 100));
  53. target.Arrange(new Rect(0, 0, 100, 100));
  54. Assert.Equal(10, target.Panel.Children.Count);
  55. }
  56. [Fact]
  57. public void Should_Only_Create_Enough_Containers_To_Display_All_Items()
  58. {
  59. var target = CreateTarget(itemCount: 2);
  60. target.ApplyTemplate();
  61. target.Measure(new Size(100, 100));
  62. target.Arrange(new Rect(0, 0, 100, 100));
  63. Assert.Equal(2, target.Panel.Children.Count);
  64. }
  65. [Fact]
  66. public void Initial_Item_DataContexts_Should_Be_Correct()
  67. {
  68. var target = CreateTarget();
  69. var items = (IList<string>)target.Items;
  70. target.ApplyTemplate();
  71. target.Measure(new Size(100, 100));
  72. target.Arrange(new Rect(0, 0, 100, 100));
  73. for (var i = 0; i < target.Panel.Children.Count; ++i)
  74. {
  75. Assert.Equal(items[i], target.Panel.Children[i].DataContext);
  76. }
  77. }
  78. [Fact]
  79. public void Should_Add_New_Items_When_Control_Is_Enlarged()
  80. {
  81. var target = CreateTarget();
  82. var items = (IList<string>)target.Items;
  83. target.ApplyTemplate();
  84. target.Measure(new Size(100, 100));
  85. target.Arrange(new Rect(0, 0, 100, 100));
  86. Assert.Equal(10, target.Panel.Children.Count);
  87. target.Arrange(new Rect(0, 0, 100, 120));
  88. Assert.Equal(12, target.Panel.Children.Count);
  89. for (var i = 0; i < target.Panel.Children.Count; ++i)
  90. {
  91. Assert.Equal(items[i], target.Panel.Children[i].DataContext);
  92. }
  93. }
  94. public class Simple
  95. {
  96. [Fact]
  97. public void Should_Return_Items_Count_For_Extent_Vertical()
  98. {
  99. var target = CreateTarget();
  100. target.ApplyTemplate();
  101. Assert.Equal(new Size(0, 20), ((IScrollable)target).Extent);
  102. }
  103. [Fact]
  104. public void Should_Return_Items_Count_For_Extent_Horizontal()
  105. {
  106. var target = CreateTarget(orientation: Orientation.Horizontal);
  107. target.ApplyTemplate();
  108. Assert.Equal(new Size(20, 0), ((IScrollable)target).Extent);
  109. }
  110. [Fact]
  111. public void Should_Have_Number_Of_Visible_Items_As_Viewport_Vertical()
  112. {
  113. var target = CreateTarget();
  114. target.ApplyTemplate();
  115. target.Measure(new Size(100, 100));
  116. target.Arrange(new Rect(0, 0, 100, 100));
  117. Assert.Equal(new Size(0, 10), ((IScrollable)target).Viewport);
  118. }
  119. [Fact]
  120. public void Should_Have_Number_Of_Visible_Items_As_Viewport_Horizontal()
  121. {
  122. var target = CreateTarget(orientation: Orientation.Horizontal);
  123. target.ApplyTemplate();
  124. target.Measure(new Size(100, 100));
  125. target.Arrange(new Rect(0, 0, 100, 100));
  126. Assert.Equal(new Size(10, 0), ((IScrollable)target).Viewport);
  127. }
  128. [Fact]
  129. public void Should_Remove_Items_When_Control_Is_Shrank()
  130. {
  131. var target = CreateTarget();
  132. var items = (IList<string>)target.Items;
  133. target.ApplyTemplate();
  134. target.Measure(new Size(100, 100));
  135. target.Arrange(new Rect(0, 0, 100, 100));
  136. Assert.Equal(10, target.Panel.Children.Count);
  137. target.Arrange(new Rect(0, 0, 100, 80));
  138. Assert.Equal(8, target.Panel.Children.Count);
  139. }
  140. [Fact]
  141. public void Scrolling_Less_Than_A_Page_Should_Move_Recycled_Items()
  142. {
  143. var target = CreateTarget();
  144. var items = (IList<string>)target.Items;
  145. target.ApplyTemplate();
  146. target.Measure(new Size(100, 100));
  147. target.Arrange(new Rect(0, 0, 100, 100));
  148. var containers = target.Panel.Children.ToList();
  149. var scroller = (ScrollContentPresenter)target.Parent;
  150. scroller.Offset = new Vector(0, 5);
  151. var scrolledContainers = containers
  152. .Skip(5)
  153. .Take(5)
  154. .Concat(containers.Take(5)).ToList();
  155. Assert.Equal(new Vector(0, 5), ((IScrollable)target).Offset);
  156. Assert.Equal(scrolledContainers, target.Panel.Children);
  157. for (var i = 0; i < target.Panel.Children.Count; ++i)
  158. {
  159. Assert.Equal(items[i + 5], target.Panel.Children[i].DataContext);
  160. }
  161. scroller.Offset = new Vector(0, 0);
  162. Assert.Equal(new Vector(0, 0), ((IScrollable)target).Offset);
  163. Assert.Equal(containers, target.Panel.Children);
  164. for (var i = 0; i < target.Panel.Children.Count; ++i)
  165. {
  166. Assert.Equal(items[i], target.Panel.Children[i].DataContext);
  167. }
  168. }
  169. [Fact]
  170. public void Scrolling_More_Than_A_Page_Should_Recycle_Items()
  171. {
  172. var target = CreateTarget();
  173. var items = (IList<string>)target.Items;
  174. target.ApplyTemplate();
  175. target.Measure(new Size(100, 100));
  176. target.Arrange(new Rect(0, 0, 100, 100));
  177. var containers = target.Panel.Children.ToList();
  178. var scroller = (ScrollContentPresenter)target.Parent;
  179. scroller.Offset = new Vector(0, 10);
  180. Assert.Equal(new Vector(0, 10), ((IScrollable)target).Offset);
  181. Assert.Equal(containers, target.Panel.Children);
  182. for (var i = 0; i < target.Panel.Children.Count; ++i)
  183. {
  184. Assert.Equal(items[i + 10], target.Panel.Children[i].DataContext);
  185. }
  186. }
  187. }
  188. private static ItemsPresenter CreateTarget(
  189. ItemVirtualizationMode mode = ItemVirtualizationMode.Simple,
  190. Orientation orientation = Orientation.Vertical,
  191. int itemCount = 20)
  192. {
  193. ItemsPresenter result;
  194. var items = Enumerable.Range(0, itemCount).Select(x => $"Item {x}").ToList();
  195. var scroller = new ScrollContentPresenter
  196. {
  197. Content = result = new ItemsPresenter
  198. {
  199. Items = items,
  200. ItemsPanel = VirtualizingPanelTemplate(orientation),
  201. ItemTemplate = ItemTemplate(),
  202. VirtualizationMode = mode,
  203. }
  204. };
  205. scroller.UpdateChild();
  206. return result;
  207. }
  208. private static IDataTemplate ItemTemplate()
  209. {
  210. return new FuncDataTemplate<string>(x => new Canvas
  211. {
  212. Width = 10,
  213. Height = 10,
  214. });
  215. }
  216. private static ITemplate<IPanel> VirtualizingPanelTemplate(
  217. Orientation orientation = Orientation.Vertical)
  218. {
  219. return new FuncTemplate<IPanel>(() => new VirtualizingStackPanel
  220. {
  221. Orientation = orientation,
  222. });
  223. }
  224. }
  225. }