diff --git a/src/Avalonia.Controls/Repeater/IElementFactory.cs b/src/Avalonia.Controls/Repeater/IElementFactory.cs
new file mode 100644
index 0000000000..6a899a6f26
--- /dev/null
+++ b/src/Avalonia.Controls/Repeater/IElementFactory.cs
@@ -0,0 +1,66 @@
+using Avalonia.Controls.Templates;
+
+namespace Avalonia.Controls
+{
+ ///
+ /// Represents the optional arguments to use when calling an implementation of the
+ /// 's method.
+ ///
+ public class ElementFactoryGetArgs
+ {
+ ///
+ /// Gets or sets the data item for which an appropriate element tree should be realized
+ /// when calling .
+ ///
+ public object Data { get; set; }
+
+ ///
+ /// Gets or sets the that is expected to be the parent of the
+ /// realized element from .
+ ///
+ public IControl Parent { get; set; }
+
+ ///
+ /// Gets or sets the index of the item that should be realized.
+ ///
+ public int Index { get; set; }
+ }
+
+ ///
+ /// Represents the optional arguments to use when calling an implementation of the
+ /// 's method.
+ ///
+ public class ElementFactoryRecycleArgs
+ {
+ ///
+ /// Gets or sets the to recycle when calling
+ /// .
+ ///
+ public IControl Element { get; set; }
+
+ ///
+ /// Gets or sets the that is expected to be the parent of the
+ /// realized element from .
+ ///
+ public IControl Parent { get; set; }
+ }
+
+ ///
+ /// A data template that supports creating and recyling elements for an .
+ ///
+ public interface IElementFactory : IDataTemplate
+ {
+ ///
+ /// Gets an .
+ ///
+ /// The element args.
+ public IControl GetElement(ElementFactoryGetArgs args);
+
+ ///
+ /// Recycles an that was previously retrieved using
+ /// .
+ ///
+ /// The recycle args.
+ public void RecycleElement(ElementFactoryRecycleArgs args);
+ }
+}
diff --git a/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs b/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs
index 04d859c742..4b784375a9 100644
--- a/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs
+++ b/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs
@@ -7,13 +7,27 @@ using Avalonia.Controls.Templates;
namespace Avalonia.Controls
{
- internal class ItemTemplateWrapper
+ internal class ItemTemplateWrapper : IElementFactory
{
private readonly IDataTemplate _dataTemplate;
public ItemTemplateWrapper(IDataTemplate dataTemplate) => _dataTemplate = dataTemplate;
- public IControl GetElement(IControl parent, object data)
+ public bool SupportsRecycling => false;
+ public IControl Build(object param) => GetElement(null, param);
+ public bool Match(object data) => _dataTemplate.Match(data);
+
+ public IControl GetElement(ElementFactoryGetArgs args)
+ {
+ return GetElement(args.Parent, args.Data);
+ }
+
+ public void RecycleElement(ElementFactoryRecycleArgs args)
+ {
+ RecycleElement(args.Parent, args.Element);
+ }
+
+ private IControl GetElement(IControl parent, object data)
{
var selectedTemplate = _dataTemplate;
var recyclePool = RecyclePool.GetPoolInstance(selectedTemplate);
@@ -37,7 +51,7 @@ namespace Avalonia.Controls
return element;
}
- public void RecycleElement(IControl parent, IControl element)
+ private void RecycleElement(IControl parent, IControl element)
{
var selectedTemplate = _dataTemplate;
var recyclePool = RecyclePool.GetPoolInstance(selectedTemplate);
diff --git a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
index 87f4760156..8bc356bdec 100644
--- a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
+++ b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
@@ -141,7 +141,7 @@ namespace Avalonia.Controls
///
public ItemsSourceView ItemsSourceView { get; private set; }
- internal ItemTemplateWrapper ItemTemplateShim { get; set; }
+ internal IElementFactory ItemTemplateShim { get; set; }
internal Point LayoutOrigin { get; set; }
internal object LayoutState { get; set; }
internal IControl MadeAnchor => _viewportManager.MadeAnchor;
@@ -664,7 +664,7 @@ namespace Avalonia.Controls
}
}
- ItemTemplateShim = new ItemTemplateWrapper(newValue);
+ ItemTemplateShim = newValue as IElementFactory ?? new ItemTemplateWrapper(newValue);
InvalidateMeasure();
}
diff --git a/src/Avalonia.Controls/Repeater/ViewManager.cs b/src/Avalonia.Controls/Repeater/ViewManager.cs
index eff51804b9..416b1e2824 100644
--- a/src/Avalonia.Controls/Repeater/ViewManager.cs
+++ b/src/Avalonia.Controls/Repeater/ViewManager.cs
@@ -6,11 +6,9 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
-using System.Linq;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Interactivity;
-using Avalonia.Layout;
using Avalonia.Logging;
using Avalonia.VisualTree;
@@ -26,6 +24,8 @@ namespace Avalonia.Controls
private readonly UniqueIdElementPool _resetPool;
private IControl _lastFocusedElement;
private bool _isDataSourceStableResetPending;
+ private ElementFactoryGetArgs _elementFactoryGetArgs;
+ private ElementFactoryRecycleArgs _elementFactoryRecycleArgs;
private int _firstRealizedElementIndexHeldByLayout = FirstRealizedElementIndexDefault;
private int _lastRealizedElementIndexHeldByLayout = LastRealizedElementIndexDefault;
private bool _eventsSubscribed;
@@ -134,7 +134,14 @@ namespace Avalonia.Controls
if (_owner.ItemTemplateShim != null)
{
- _owner.ItemTemplateShim.RecycleElement(_owner, element);
+ var context = _elementFactoryRecycleArgs ??= new ElementFactoryRecycleArgs();
+ context.Element = element;
+ context.Parent = _owner;
+
+ _owner.ItemTemplateShim.RecycleElement(context);
+
+ context.Element = null;
+ context.Parent = null;
}
else
{
@@ -579,7 +586,7 @@ namespace Avalonia.Controls
var data = _owner.ItemsSourceView.GetAt(index);
var providedElementFactory = _owner.ItemTemplateShim;
- ItemTemplateWrapper GetElementFactory()
+ IElementFactory GetElementFactory()
{
if (providedElementFactory == null)
{
@@ -602,7 +609,20 @@ namespace Avalonia.Controls
}
var elementFactory = GetElementFactory();
- return elementFactory.GetElement(_owner, data);
+ var args = _elementFactoryGetArgs ??= new ElementFactoryGetArgs();
+
+ try
+ {
+ args.Data = data;
+ args.Parent = _owner;
+ args.Index = index;
+ return elementFactory.GetElement(args);
+ }
+ finally
+ {
+ args.Data = null;
+ args.Parent = null;
+ }
}
var element = GetElement();
@@ -732,6 +752,7 @@ namespace Avalonia.Controls
{
_owner.GotFocus += OnFocusChanged;
_owner.LostFocus += OnFocusChanged;
+ _eventsSubscribed = true;
}
}