diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs
index a7d1de5777..dd7cf3bf1d 100644
--- a/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs
+++ b/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs
@@ -10,29 +10,88 @@ using Avalonia.VisualTree;
namespace Avalonia.Controls.Presenters
{
+ ///
+ /// Base class for classes which handle virtualization for an .
+ ///
internal abstract class ItemVirtualizer
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
public ItemVirtualizer(ItemsPresenter owner)
{
Owner = owner;
}
+ ///
+ /// Gets the which owns the virtualizer.
+ ///
public ItemsPresenter Owner { get; }
+
+ ///
+ /// Gets the which will host the items.
+ ///
public IVirtualizingPanel VirtualizingPanel => Owner.Panel as IVirtualizingPanel;
+
+ ///
+ /// Gets the items to display.
+ ///
public IEnumerable Items { get; private set; }
+
+ ///
+ /// Gets the number of items in .
+ ///
public int ItemCount { get; private set; }
- public int FirstIndex { get; set; }
- public int NextIndex { get; set; }
+
+ ///
+ /// Gets or sets the index of the first item displayed in the panel.
+ ///
+ public int FirstIndex { get; protected set; }
+
+ ///
+ /// Gets or sets the index of the first item beyond those displayed in the panel.
+ ///
+ public int NextIndex { get; protected set; }
+
+ ///
+ /// Gets a value indicating whether the items should be scroll horizontally or vertically.
+ ///
public bool Vertical => VirtualizingPanel.ScrollDirection == Orientation.Vertical;
+ ///
+ /// Gets a value indicating whether logical scrolling is enabled.
+ ///
public abstract bool IsLogicalScrollEnabled { get; }
+
+ ///
+ /// Gets the value of the scroll extent.
+ ///
public abstract double ExtentValue { get; }
+
+ ///
+ /// Gets or sets the value of the current scroll offset.
+ ///
public abstract double OffsetValue { get; set; }
+
+ ///
+ /// Gets the value of the scrollable viewport.
+ ///
public abstract double ViewportValue { get; }
+ ///
+ /// Gets the as a .
+ ///
public Size Extent => Vertical ? new Size(0, ExtentValue) : new Size(ExtentValue, 0);
+
+ ///
+ /// Gets the as a .
+ ///
public Size Viewport => Vertical ? new Size(0, ViewportValue) : new Size(ViewportValue, 0);
+ ///
+ /// Gets or sets the as a .
+ ///
public Vector Offset
{
get
@@ -46,6 +105,12 @@ namespace Avalonia.Controls.Presenters
}
}
+ ///
+ /// Creates an based on an item presenter's
+ /// .
+ ///
+ /// The items presenter.
+ /// An .
public static ItemVirtualizer Create(ItemsPresenter owner)
{
var virtualizingPanel = owner.Panel as IVirtualizingPanel;
@@ -63,13 +128,30 @@ namespace Avalonia.Controls.Presenters
return new ItemVirtualizerNone(owner);
}
+ ///
+ /// Called by the when it carries out an arrange.
+ ///
+ /// The final size passed to the arrange.
public abstract void Arranging(Size finalSize);
+ ///
+ /// Called when a request is made to bring an item into view.
+ ///
+ /// The item to bring into view.
+ /// The rect on the item to bring into view.
+ /// True if the request was handled; otherwise false.
public virtual bool BringIntoView(IVisual target, Rect targetRect)
{
return false;
}
+ ///
+ /// Called when the items for the presenter change, either because
+ /// has been set, the items collection has been
+ /// modified, or the panel has been created.
+ ///
+ /// The items.
+ /// A description of the change.
public virtual void ItemsChanged(IEnumerable items, NotifyCollectionChangedEventArgs e)
{
Items = items;
diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs
index a8c24fcf72..303c7442c2 100644
--- a/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs
+++ b/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs
@@ -10,6 +10,10 @@ using Avalonia.Controls.Utils;
namespace Avalonia.Controls.Presenters
{
+ ///
+ /// Represents an item virtualizer for an that doesn't actually
+ /// virtualize items - it just creates a container for every item.
+ ///
internal class ItemVirtualizerNone : ItemVirtualizer
{
public ItemVirtualizerNone(ItemsPresenter owner)
@@ -17,29 +21,44 @@ namespace Avalonia.Controls.Presenters
{
}
+ ///
public override bool IsLogicalScrollEnabled => false;
+ ///
+ /// This property should never be accessed because is
+ /// false.
+ ///
public override double ExtentValue
{
get { throw new NotSupportedException(); }
}
+ ///
+ /// This property should never be accessed because is
+ /// false.
+ ///
public override double OffsetValue
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
+ ///
+ /// This property should never be accessed because is
+ /// false.
+ ///
public override double ViewportValue
{
get { throw new NotSupportedException(); }
}
+ ///
public override void Arranging(Size finalSize)
{
// We don't need to do anything here.
}
+ ///
public override void ItemsChanged(IEnumerable items, NotifyCollectionChangedEventArgs e)
{
base.ItemsChanged(items, e);
@@ -47,7 +66,6 @@ namespace Avalonia.Controls.Presenters
var generator = Owner.ItemContainerGenerator;
var panel = Owner.Panel;
- // TODO: Handle Move and Replace etc.
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
@@ -77,7 +95,9 @@ namespace Avalonia.Controls.Presenters
break;
case NotifyCollectionChangedAction.Move:
- // TODO: Implement Move in a more efficient manner.
+ // TODO: Handle move in a more efficient manner. At the moment we just
+ // drop through to Reset to recreate all the containers.
+
case NotifyCollectionChangedAction.Reset:
RemoveContainers(generator.Clear());
diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
index 01b1b24e43..69141fdbea 100644
--- a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
+++ b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
@@ -10,17 +10,28 @@ using Avalonia.Controls.Utils;
namespace Avalonia.Controls.Presenters
{
+ ///
+ /// Handles virtualization in an for
+ /// .
+ ///
internal class ItemVirtualizerSimple : ItemVirtualizer
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
public ItemVirtualizerSimple(ItemsPresenter owner)
: base(owner)
{
}
+ ///
public override bool IsLogicalScrollEnabled => true;
+ ///
public override double ExtentValue => ItemCount;
+ ///
public override double OffsetValue
{
get
@@ -61,6 +72,7 @@ namespace Avalonia.Controls.Presenters
}
}
+ ///
public override double ViewportValue
{
get
@@ -71,12 +83,14 @@ namespace Avalonia.Controls.Presenters
}
}
+ ///
public override void Arranging(Size finalSize)
{
CreateAndRemoveContainers();
((ILogicalScrollable)Owner).InvalidateScroll();
}
+ ///
public override void ItemsChanged(IEnumerable items, NotifyCollectionChangedEventArgs e)
{
base.ItemsChanged(items, e);
@@ -123,6 +137,10 @@ namespace Avalonia.Controls.Presenters
((ILogicalScrollable)Owner).InvalidateScroll();
}
+ ///
+ /// Creates and removes containers such that we have at most enough containers to fill
+ /// the panel.
+ ///
private void CreateAndRemoveContainers()
{
var generator = Owner.ItemContainerGenerator;
@@ -184,6 +202,14 @@ namespace Avalonia.Controls.Presenters
}
}
+ ///
+ /// Updates the containers in the panel to make sure they are displaying the correct item
+ /// based on .
+ ///
+ ///
+ /// This method requires that + the number of
+ /// materialized containers is not more than .
+ ///
private void RecycleContainers()
{
var panel = VirtualizingPanel;
@@ -208,6 +234,19 @@ namespace Avalonia.Controls.Presenters
}
}
+ ///
+ /// Recycles containers when a move occurs.
+ ///
+ /// The delta of the move.
+ ///
+ /// If the move is less than a page, then this method moves the containers for the items
+ /// that are still visible to the correct place, and recyles and moves the others. For
+ /// example: if there are 20 items and 10 containers visible and the user scrolls 5
+ /// items down, then the bottom 5 containers will be moved to the top and the top 5 will
+ /// be moved to the bottom and recycled to display the newly visible item. Updates
+ /// and
+ /// with their new values.
+ ///
private void RecycleContainersForMove(int delta)
{
var panel = VirtualizingPanel;
@@ -250,6 +289,9 @@ namespace Avalonia.Controls.Presenters
NextIndex += delta;
}
+ ///
+ /// Recycles containers due to items being removed.
+ ///
private void RecycleContainersOnRemove()
{
var panel = VirtualizingPanel;
@@ -283,6 +325,11 @@ namespace Avalonia.Controls.Presenters
}
}
+ ///
+ /// Removes the specified number of containers from the end of the panel and updates
+ /// .
+ ///
+ /// The number of containers to remove.
private void RemoveContainers(int count)
{
var index = VirtualizingPanel.Children.Count - count;