Browse Source

Ported IElementFactory from UWP/WinUI.

pull/4218/head
Steven Kirk 6 years ago
parent
commit
f545fb2a4d
  1. 66
      src/Avalonia.Controls/Repeater/IElementFactory.cs
  2. 20
      src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs
  3. 4
      src/Avalonia.Controls/Repeater/ItemsRepeater.cs
  4. 31
      src/Avalonia.Controls/Repeater/ViewManager.cs

66
src/Avalonia.Controls/Repeater/IElementFactory.cs

@ -0,0 +1,66 @@
using Avalonia.Controls.Templates;
namespace Avalonia.Controls
{
/// <summary>
/// Represents the optional arguments to use when calling an implementation of the
/// <see cref="IElementFactory"/>'s <see cref="IElementFactory.GetElement"/> method.
/// </summary>
public class ElementFactoryGetArgs
{
/// <summary>
/// Gets or sets the data item for which an appropriate element tree should be realized
/// when calling <see cref="IElementFactory.GetElement"/>.
/// </summary>
public object Data { get; set; }
/// <summary>
/// Gets or sets the <see cref="IControl"/> that is expected to be the parent of the
/// realized element from <see cref="IElementFactory.GetElement"/>.
/// </summary>
public IControl Parent { get; set; }
/// <summary>
/// Gets or sets the index of the item that should be realized.
/// </summary>
public int Index { get; set; }
}
/// <summary>
/// Represents the optional arguments to use when calling an implementation of the
/// <see cref="IElementFactory"/>'s <see cref="IElementFactory.GetElement"/> method.
/// </summary>
public class ElementFactoryRecycleArgs
{
/// <summary>
/// Gets or sets the <see cref="IControl"/> to recycle when calling
/// <see cref="IElementFactory.RecycleElement"/>.
/// </summary>
public IControl Element { get; set; }
/// <summary>
/// Gets or sets the <see cref="IControl"/> that is expected to be the parent of the
/// realized element from <see cref="IElementFactory.GetElement"/>.
/// </summary>
public IControl Parent { get; set; }
}
/// <summary>
/// A data template that supports creating and recyling elements for an <see cref="ItemsRepeater"/>.
/// </summary>
public interface IElementFactory : IDataTemplate
{
/// <summary>
/// Gets an <see cref="IControl"/>.
/// </summary>
/// <param name="args">The element args.</param>
public IControl GetElement(ElementFactoryGetArgs args);
/// <summary>
/// Recycles an <see cref="IControl"/> that was previously retrieved using
/// <see cref="GetElement"/>.
/// </summary>
/// <param name="args">The recycle args.</param>
public void RecycleElement(ElementFactoryRecycleArgs args);
}
}

20
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);

4
src/Avalonia.Controls/Repeater/ItemsRepeater.cs

@ -141,7 +141,7 @@ namespace Avalonia.Controls
/// </summary>
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();
}

31
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;
}
}

Loading…
Cancel
Save