Browse Source

Don't add virt items when attached to visual tree.

Don't add virtualized items before the virtualizing panel is attached to
the visual tree, as bindings etc won't be set and so measurement will
produce 0,0 causing all items to be materialized.
pull/579/head
Steven Kirk 10 years ago
parent
commit
5a72ed8586
  1. 3
      src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
  2. 4
      tests/Avalonia.Controls.UnitTests/ListBoxTests.cs
  3. 56
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs
  4. 19
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs

3
src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs

@ -9,6 +9,7 @@ using Avalonia.Controls.Utils;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Layout; using Avalonia.Layout;
using Avalonia.Utilities; using Avalonia.Utilities;
using Avalonia.VisualTree;
namespace Avalonia.Controls.Presenters namespace Avalonia.Controls.Presenters
{ {
@ -245,7 +246,7 @@ namespace Avalonia.Controls.Presenters
var generator = Owner.ItemContainerGenerator; var generator = Owner.ItemContainerGenerator;
var panel = VirtualizingPanel; var panel = VirtualizingPanel;
if (!panel.IsFull && Items != null) if (!panel.IsFull && Items != null && panel.IsAttachedToVisualTree)
{ {
var memberSelector = Owner.MemberSelector; var memberSelector = Owner.MemberSelector;
var index = NextIndex; var index = NextIndex;

4
tests/Avalonia.Controls.UnitTests/ListBoxTests.cs

@ -194,6 +194,10 @@ namespace Avalonia.Controls.UnitTests
private void Prepare(ListBox target) private void Prepare(ListBox target)
{ {
// The ListBox needs to be part of a rooted visual tree.
var root = new TestRoot();
root.Child = target;
// Apply the template to the ListBox itself. // Apply the template to the ListBox itself.
target.ApplyTemplate(); target.ApplyTemplate();

56
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs

@ -1,6 +1,7 @@
// Copyright (c) The Avalonia Project. All rights reserved. // Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Avalonia.Controls.Generators; using Avalonia.Controls.Generators;
@ -8,6 +9,7 @@ using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Layout; using Avalonia.Layout;
using Avalonia.Rendering;
using Avalonia.UnitTests; using Avalonia.UnitTests;
using Xunit; using Xunit;
@ -15,6 +17,43 @@ namespace Avalonia.Controls.UnitTests.Presenters
{ {
public class ItemsPresenterTests_Virtualization public class ItemsPresenterTests_Virtualization
{ {
[Fact]
public void Should_Not_Create_Items_Before_Added_To_Visual_Tree()
{
var items = Enumerable.Range(0, 10).Select(x => $"Item {x}").ToList();
var target = new TestItemsPresenter(true)
{
Items = items,
ItemsPanel = VirtualizingPanelTemplate(Orientation.Vertical),
ItemTemplate = ItemTemplate(),
VirtualizationMode = ItemVirtualizationMode.Simple,
};
var scroller = new ScrollContentPresenter
{
Content = target,
};
scroller.UpdateChild();
target.ApplyTemplate();
target.Measure(new Size(100, 100));
target.Arrange(new Rect(0, 0, 100, 100));
Assert.Empty(target.Panel.Children);
var root = new TestRoot
{
Child = scroller,
};
target.InvalidateMeasure();
target.Panel.InvalidateMeasure();
target.Measure(new Size(100, 100));
target.Arrange(new Rect(0, 0, 100, 100));
Assert.Equal(10, target.Panel.Children.Count);
}
[Fact] [Fact]
public void Should_Return_IsLogicalScrollEnabled_False_When_Has_No_Virtualizing_Panel() public void Should_Return_IsLogicalScrollEnabled_False_When_Has_No_Virtualizing_Panel()
{ {
@ -239,7 +278,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
ItemsPresenter result; ItemsPresenter result;
var items = Enumerable.Range(0, itemCount).Select(x => $"Item {x}").ToList(); var items = Enumerable.Range(0, itemCount).Select(x => $"Item {x}").ToList();
var scroller = new ScrollContentPresenter var scroller = new TestScroller
{ {
Content = result = new TestItemsPresenter(useContainers) Content = result = new TestItemsPresenter(useContainers)
{ {
@ -273,6 +312,21 @@ namespace Avalonia.Controls.UnitTests.Presenters
}); });
} }
private class TestScroller : ScrollContentPresenter, IRenderRoot
{
public IRenderQueueManager RenderQueueManager { get; }
public Point PointToClient(Point point)
{
throw new NotImplementedException();
}
public Point PointToScreen(Point point)
{
throw new NotImplementedException();
}
}
private class TestItemsPresenter : ItemsPresenter private class TestItemsPresenter : ItemsPresenter
{ {
private bool _useContainers; private bool _useContainers;

19
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs

@ -1,6 +1,7 @@
// Copyright (c) The Avalonia Project. All rights reserved. // Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -11,6 +12,7 @@ using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Rendering;
using Avalonia.UnitTests; using Avalonia.UnitTests;
using Xunit; using Xunit;
@ -730,7 +732,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
(IEnumerable)new AvaloniaList<string>(itemsSource) : (IEnumerable)new AvaloniaList<string>(itemsSource) :
(IEnumerable)new ObservableCollection<string>(itemsSource); (IEnumerable)new ObservableCollection<string>(itemsSource);
var scroller = new ScrollContentPresenter var scroller = new TestScroller
{ {
Content = result = new TestItemsPresenter(useContainers) Content = result = new TestItemsPresenter(useContainers)
{ {
@ -764,6 +766,21 @@ namespace Avalonia.Controls.UnitTests.Presenters
}); });
} }
private class TestScroller : ScrollContentPresenter, IRenderRoot
{
public IRenderQueueManager RenderQueueManager { get; }
public Point PointToClient(Point point)
{
throw new NotImplementedException();
}
public Point PointToScreen(Point point)
{
throw new NotImplementedException();
}
}
private class TestItemsPresenter : ItemsPresenter private class TestItemsPresenter : ItemsPresenter
{ {
private bool _useContainers; private bool _useContainers;

Loading…
Cancel
Save