Add iOS prototypical cell cache for LV RowHeight calcs (#1143)

This commit is contained in:
kingces95 2017-09-16 10:10:04 -04:00 коммит произвёл Rui Marinho
Родитель b47068a21e
Коммит d4480b2e48
17 изменённых файлов: 344 добавлений и 89 удалений

Просмотреть файл

@ -90,4 +90,69 @@ namespace Xamarin.Forms.Core.UnitTests
Assert.Throws<NotSupportedException> (() => dts.SelectTemplate ((byte)0, null));
}
}
[TestFixture]
public class DataTemplateRecycleTests : BaseTestFixture
{
[TearDown]
public override void TearDown()
{
base.TearDown();
Device.PlatformServices = null;
}
[SetUp]
public override void Setup()
{
base.Setup();
Device.PlatformServices = new MockPlatformServices();
}
class TestDataTemplateSelector : DataTemplateSelector
{
readonly DataTemplate declarativeTemplate;
readonly DataTemplate proceduralTemplate;
public TestDataTemplateSelector ()
{
declarativeTemplate = new DataTemplate(typeof(ViewCell));
proceduralTemplate = new DataTemplate(() => new EntryCell());
}
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
Counter++;
if (item is string)
return declarativeTemplate;
return proceduralTemplate;
}
public int Counter = 0;
}
[Test]
public void ListViewSupport ()
{
var listView = new ListView(ListViewCachingStrategy.RecycleElementAndDataTemplate);
listView.ItemsSource = new object[] { "foo", "bar", 0 };
Assert.That(listView.CachingStrategy ==
ListViewCachingStrategy.RecycleElementAndDataTemplate);
var selector = new TestDataTemplateSelector();
listView.ItemTemplate = selector;
Assert.That(selector.Counter == 0);
Assert.IsInstanceOf<ViewCell>(listView.TemplatedItems[0]);
Assert.That(selector.Counter == 1);
Assert.IsInstanceOf<ViewCell>(listView.TemplatedItems[1]);
Assert.That(selector.Counter == 1);
Assert.Throws<NotSupportedException>(
() => { var o = listView.TemplatedItems[2]; });
}
}
}

Просмотреть файл

@ -5,14 +5,18 @@ namespace Xamarin.Forms.Internals
[EditorBrowsable(EditorBrowsableState.Never)]
public static class DataTemplateExtensions
{
public static object CreateContent(this DataTemplate self, object item, BindableObject container)
public static DataTemplate SelectDataTemplate(this DataTemplate self, object item, BindableObject container)
{
var selector = self as DataTemplateSelector;
if (selector != null)
{
self = selector.SelectTemplate(item, container);
}
return self.CreateContent();
if (selector == null)
return self;
return selector.SelectTemplate(item, container);
}
public static object CreateContent(this DataTemplate self, object item, BindableObject container)
{
return self.SelectDataTemplate(item, container).CreateContent();
}
}
}

Просмотреть файл

@ -1,15 +1,39 @@
using System;
using System.Collections.Generic;
namespace Xamarin.Forms
{
public abstract class DataTemplateSelector : DataTemplate
{
Dictionary<Type, DataTemplate> _dataTemplates = new Dictionary<Type, DataTemplate>();
public DataTemplate SelectTemplate(object item, BindableObject container)
{
DataTemplate result = OnSelectTemplate(item, container);
if (result is DataTemplateSelector)
throw new NotSupportedException("DataTemplateSelector.OnSelectTemplate must not return another DataTemplateSelector");
return result;
var listView = container as ListView;
var recycle = listView == null ? false :
(listView.CachingStrategy & ListViewCachingStrategy.RecycleElementAndDataTemplate) ==
ListViewCachingStrategy.RecycleElementAndDataTemplate;
DataTemplate dataTemplate = null;
if (recycle && _dataTemplates.TryGetValue(item.GetType(), out dataTemplate))
return dataTemplate;
dataTemplate = OnSelectTemplate(item, container);
if (dataTemplate is DataTemplateSelector)
throw new NotSupportedException(
"DataTemplateSelector.OnSelectTemplate must not return another DataTemplateSelector");
if (recycle)
{
if (!dataTemplate.CanRecycle)
throw new NotSupportedException(
"RecycleElementAndDataTemplate requires DataTemplate activated with ctor taking a type.");
_dataTemplates[item.GetType()] = dataTemplate;
}
return dataTemplate;
}
protected abstract DataTemplate OnSelectTemplate(object item, BindableObject container);

Просмотреть файл

@ -10,6 +10,7 @@ namespace Xamarin.Forms
{
List<Action<object, ResourcesChangedEventArgs>> _changeHandlers;
Element _parent;
bool _canRecycle; // aka IsDeclarative
internal ElementTemplate()
{
@ -20,6 +21,8 @@ namespace Xamarin.Forms
if (type == null)
throw new ArgumentNullException("type");
_canRecycle = true;
LoadTemplate = () => Activator.CreateInstance(type);
}
@ -46,6 +49,7 @@ namespace Xamarin.Forms
_changeHandlers.Add(onchanged);
}
internal bool CanRecycle => _canRecycle;
Element IElement.Parent
{
get { return _parent; }

Просмотреть файл

@ -19,6 +19,7 @@ namespace Xamarin.Forms
IListProxy ListProxy { get; }
DataTemplate SelectDataTemplate(object item);
int GetGlobalIndexForGroup(ITemplatedItemsList<TItem> group);
int GetGlobalIndexOfItem(object item);
ITemplatedItemsList<TItem> GetGroup(int index);

Просмотреть файл

@ -86,13 +86,18 @@ namespace Xamarin.Forms
element.Parent = (Element)bindable;
}
static bool ValidateItemTemplate(BindableObject b, object v)
static bool ValidateItemTemplate(BindableObject bindable, object value)
{
var lv = b as ListView;
if (lv == null)
var listView = bindable as ListView;
if (listView == null)
return true;
return !(lv.CachingStrategy == ListViewCachingStrategy.RetainElement && lv.ItemTemplate is DataTemplateSelector);
var isRetainStrategy = listView.CachingStrategy == ListViewCachingStrategy.RetainElement;
var isDataTemplateSelector = listView.ItemTemplate is DataTemplateSelector;
if (isRetainStrategy && isDataTemplateSelector)
return false;
return true;
}
}
}

Просмотреть файл

@ -73,7 +73,11 @@ namespace Xamarin.Forms
public ListView([Parameter("CachingStrategy")] ListViewCachingStrategy cachingStrategy) : this()
{
if (Device.RuntimePlatform == Device.Android || Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.macOS)
// null => UnitTest "platform"
if (Device.RuntimePlatform == null ||
Device.RuntimePlatform == Device.Android ||
Device.RuntimePlatform == Device.iOS ||
Device.RuntimePlatform == Device.macOS)
CachingStrategy = cachingStrategy;
}

Просмотреть файл

@ -1,8 +1,12 @@
using System;
namespace Xamarin.Forms
{
[Flags]
public enum ListViewCachingStrategy
{
RetainElement = 0,
RecycleElement
RecycleElement = 1 << 0,
RecycleElementAndDataTemplate = RecycleElement | 1 << 1,
}
}

Просмотреть файл

@ -523,13 +523,19 @@ namespace Xamarin.Forms.Internals
return GetIndex(item);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public DataTemplate SelectDataTemplate(object item)
{
return ItemTemplate.SelectDataTemplate(item, _itemsView);
}
public TItem CreateContent(int index, object item, bool insert = false)
{
TItem content = ItemTemplate != null ? (TItem)ItemTemplate.CreateContent(item, _itemsView) : _itemsView.CreateDefault(item);
content = UpdateContent(content, index, item);
if (CachingStrategy == ListViewCachingStrategy.RecycleElement)
if ((CachingStrategy & ListViewCachingStrategy.RecycleElement) != 0)
return content;
for (int i = _templatedObjects.Count; i <= index; i++)
@ -891,7 +897,7 @@ namespace Xamarin.Forms.Internals
void OnGroupingEnabledChanged()
{
if (CachingStrategy == ListViewCachingStrategy.RecycleElement)
if ((CachingStrategy & ListViewCachingStrategy.RecycleElement) != 0)
_templatedObjects.Clear();
OnItemsSourceChanged(true);
@ -963,7 +969,7 @@ namespace Xamarin.Forms.Internals
return;
}
if (CachingStrategy == ListViewCachingStrategy.RecycleElement)
if ((CachingStrategy & ListViewCachingStrategy.RecycleElement) != 0)
{
OnCollectionChanged(e);
return;

Просмотреть файл

@ -162,7 +162,7 @@ namespace Xamarin.Forms.Platform.MacOS
cell = GetCellForPath(indexPath, isHeader);
nativeCell = CellNSView.GetNativeCell(tableView, cell, templateId, isHeader);
}
else if (cachingStrategy == ListViewCachingStrategy.RecycleElement)
else if ((cachingStrategy & ListViewCachingStrategy.RecycleElement) != 0)
{
nativeCell = tableView.MakeView(templateId, tableView);
if (nativeCell == null)

Просмотреть файл

@ -118,7 +118,8 @@ namespace Xamarin.Forms.Platform.iOS
public void Update(UITableView tableView, Cell cell, UITableViewCell nativeCell)
{
var parentListView = cell.RealParent as ListView;
var recycling = parentListView != null && parentListView.CachingStrategy == ListViewCachingStrategy.RecycleElement;
var recycling = parentListView != null &&
((parentListView.CachingStrategy & ListViewCachingStrategy.RecycleElement) != 0);
if (_cell != cell && recycling)
{
if (_cell != null)
@ -459,7 +460,8 @@ namespace Xamarin.Forms.Platform.iOS
if (e.PropertyName == "HasContextActions")
{
var parentListView = _cell.RealParent as ListView;
var recycling = parentListView != null && parentListView.CachingStrategy == ListViewCachingStrategy.RecycleElement;
var recycling = parentListView != null &&
((parentListView.CachingStrategy & ListViewCachingStrategy.RecycleElement) != 0);
if (!recycling)
ReloadRow();
}
@ -468,7 +470,8 @@ namespace Xamarin.Forms.Platform.iOS
void OnContextItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
var parentListView = _cell.RealParent as ListView;
var recycling = parentListView != null && parentListView.CachingStrategy == ListViewCachingStrategy.RecycleElement;
var recycling = parentListView != null &&
((parentListView.CachingStrategy & ListViewCachingStrategy.RecycleElement) != 0);
if (recycling)
Update(_tableView, _cell, ContentCell);
else
@ -479,7 +482,8 @@ namespace Xamarin.Forms.Platform.iOS
void OnMenuItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var parentListView = _cell.RealParent as ListView;
var recycling = parentListView != null && parentListView.CachingStrategy == ListViewCachingStrategy.RecycleElement;
var recycling = parentListView != null &&
((parentListView.CachingStrategy & ListViewCachingStrategy.RecycleElement) != 0);
if (recycling)
Update(_tableView, _cell, ContentCell);
else

Просмотреть файл

@ -25,7 +25,6 @@ namespace Xamarin.Forms.Platform.iOS
KeyboardInsetTracker _insetTracker;
RectangleF _previousFrame;
ScrollToRequestedEventArgs _requestedScroll;
bool _shouldEstimateRowHeight = true;
FormsUITableViewController _tableViewController;
ListView ListView => Element;
@ -212,7 +211,6 @@ namespace Xamarin.Forms.Platform.iOS
Control.SetContentOffset(offset, true);
});
}
_shouldEstimateRowHeight = true;
var listView = e.NewElement;
@ -366,35 +364,36 @@ namespace Xamarin.Forms.Platform.iOS
void UpdateEstimatedRowHeight()
{
var rowHeight = Element.RowHeight;
if (Element.HasUnevenRows && rowHeight == -1)
{
var source = _dataSource as UnevenListViewDataSource;
if (_estimatedRowHeight)
return;
// We want to make sure we reset the cached defined row heights whenever this is called.
// Failing to do this will regress Bugzilla 43313 (strange animation when adding rows with uneven heights)
source?.CacheDefinedRowHeights();
if (_shouldEstimateRowHeight && !_estimatedRowHeight)
{
if (source != null)
{
Control.EstimatedRowHeight = source.GetEstimatedRowHeight(Control);
_estimatedRowHeight = true;
}
else
{
//We need to set a default estimated row height, because re-setting it later(when we have items on the TIL)
//will cause the UITableView to reload, and throw an Exception
Control.EstimatedRowHeight = DefaultRowHeight;
}
}
}
else if (!_estimatedRowHeight)
// if even rows OR uneven rows but user specified a row height anyway...
if (!Element.HasUnevenRows || Element.RowHeight != -1)
{
Control.EstimatedRowHeight = 0;
_estimatedRowHeight = true;
return;
}
var source = _dataSource as UnevenListViewDataSource;
// We want to make sure we reset the cached defined row heights whenever this is called.
// Failing to do this will regress Bugzilla 43313
// (strange animation when adding rows with uneven heights)
//source?.CacheDefinedRowHeights();
if (source == null)
{
// We need to set a default estimated row height,
// because re-setting it later(when we have items on the TIL)
// will cause the UITableView to reload, and throw an Exception
Control.EstimatedRowHeight = DefaultRowHeight;
return;
}
Control.EstimatedRowHeight = source.GetEstimatedRowHeight(Control);
_estimatedRowHeight = true;
return;
}
void UpdateFooter()
@ -627,9 +626,7 @@ namespace Xamarin.Forms.Platform.iOS
{
IVisualElementRenderer _prototype;
bool _disposed;
bool _useEstimatedRowHeight;
ConcurrentDictionary<NSIndexPath, nfloat> _rowHeights = new ConcurrentDictionary<NSIndexPath, nfloat>();
Dictionary<object, Cell> _prototypicalCellByTypeOrDataTemplate = new Dictionary<object, Cell>();
public UnevenListViewDataSource(ListView list, FormsUITableViewController uiTableViewController) : base(list, uiTableViewController)
{
@ -639,24 +636,6 @@ namespace Xamarin.Forms.Platform.iOS
{
}
internal void CacheDefinedRowHeights()
{
Task.Run(() =>
{
var templatedItems = TemplatedItemsView.TemplatedItems;
foreach (var cell in templatedItems)
{
if (_disposed)
return;
double? cellRenderHeight = cell?.RenderHeight;
if (cellRenderHeight > 0)
_rowHeights[cell.GetIndexPath()] = (nfloat)cellRenderHeight;
}
});
}
internal nfloat GetEstimatedRowHeight(UITableView table)
{
if (List.RowHeight != -1)
@ -692,22 +671,42 @@ namespace Xamarin.Forms.Platform.iOS
return CalculateHeightForCell(table, firstCell);
}
public override nfloat EstimatedHeight(UITableView tableView, NSIndexPath indexPath)
internal override void InvalidatePrototypicalCellCache()
{
if (_useEstimatedRowHeight)
return tableView.EstimatedRowHeight;
_prototypicalCellByTypeOrDataTemplate.Clear();
}
// Note: It is *not* an optimization to first check if the array has any values.
nfloat specifiedRowHeight;
if (_rowHeights.TryGetValue(indexPath, out specifiedRowHeight) && specifiedRowHeight > 0)
return specifiedRowHeight;
internal Cell GetPrototypicalCell(NSIndexPath indexPath)
{
var itemTypeOrDataTemplate = default(object);
return UITableView.AutomaticDimension;
var cachingStrategy = List.CachingStrategy;
if (cachingStrategy == ListViewCachingStrategy.RecycleElement)
itemTypeOrDataTemplate = GetDataTemplateForPath(indexPath);
else if (cachingStrategy == ListViewCachingStrategy.RecycleElementAndDataTemplate)
itemTypeOrDataTemplate = GetItemTypeForPath(indexPath);
else // ListViewCachingStrategy.RetainElement
return GetCellForPath(indexPath);
Cell protoCell;
if (!_prototypicalCellByTypeOrDataTemplate.TryGetValue(itemTypeOrDataTemplate, out protoCell))
{
// cache prototypical cell by item type; Items of the same Type share
// the same DataTemplate (this is enforced by RecycleElementAndDataTemplate)
protoCell = GetCellForPath(indexPath);
_prototypicalCellByTypeOrDataTemplate[itemTypeOrDataTemplate] = protoCell;
}
var templatedItems = GetTemplatedItemsListForPath(indexPath);
return templatedItems.UpdateContent(protoCell, indexPath.Row);
}
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
var cell = GetCellForPath(indexPath);
var cell = GetPrototypicalCell(indexPath);
if (List.RowHeight == -1 && cell.Height == -1 && cell is ViewCell)
return UITableView.AutomaticDimension;
@ -745,7 +744,7 @@ namespace Xamarin.Forms.Platform.iOS
// Let the EstimatedHeight method know to use this value.
// Much more efficient than checking the value each time.
_useEstimatedRowHeight = true;
//_useEstimatedRowHeight = true;
return (nfloat)req.Request.Height;
}
@ -818,6 +817,10 @@ namespace Xamarin.Forms.Platform.iOS
get { return UIColor.Clear; }
}
internal virtual void InvalidatePrototypicalCellCache()
{
}
public override void DraggingEnded(UIScrollView scrollView, bool willDecelerate)
{
_isDragging = false;
@ -840,13 +843,14 @@ namespace Xamarin.Forms.Platform.iOS
cell = GetCellForPath(indexPath);
nativeCell = CellTableViewCell.GetNativeCell(tableView, cell);
}
else if (cachingStrategy == ListViewCachingStrategy.RecycleElement)
else if ((cachingStrategy & ListViewCachingStrategy.RecycleElement) != 0)
{
var id = TemplateIdForPath(indexPath);
nativeCell = tableView.DequeueReusableCell(ContextActionsCell.Key + id);
if (nativeCell == null)
{
cell = GetCellForPath(indexPath);
nativeCell = CellTableViewCell.GetNativeCell(tableView, cell, true, id.ToString());
}
else
@ -966,7 +970,7 @@ namespace Xamarin.Forms.Platform.iOS
return;
Cell formsCell = null;
if (List.CachingStrategy == ListViewCachingStrategy.RecycleElement)
if ((List.CachingStrategy & ListViewCachingStrategy.RecycleElement) != 0)
formsCell = (Cell)((INativeElementView)cell).Element;
SetCellBackgroundColor(cell, UIColor.Clear);
@ -1035,12 +1039,32 @@ namespace Xamarin.Forms.Platform.iOS
_uiTableView.ReloadData();
}
protected Cell GetCellForPath(NSIndexPath indexPath)
protected ITemplatedItemsList<Cell> GetTemplatedItemsListForPath(NSIndexPath indexPath)
{
var templatedItems = TemplatedItemsView.TemplatedItems;
if (List.IsGroupingEnabled)
templatedItems = (TemplatedItemsList<ItemsView<Cell>, Cell>)((IList)templatedItems)[indexPath.Section];
templatedItems = (ITemplatedItemsList<Cell>)((IList)templatedItems)[indexPath.Section];
return templatedItems;
}
protected DataTemplate GetDataTemplateForPath(NSIndexPath indexPath)
{
var templatedList = GetTemplatedItemsListForPath(indexPath);
var item = templatedList.ListProxy[indexPath.Row];
return templatedList.SelectDataTemplate(item);
}
protected Type GetItemTypeForPath(NSIndexPath indexPath)
{
var templatedList = GetTemplatedItemsListForPath(indexPath);
var item = templatedList.ListProxy[indexPath.Row];
return item.GetType();
}
protected Cell GetCellForPath(NSIndexPath indexPath)
{
var templatedItems = GetTemplatedItemsListForPath(indexPath);
var cell = templatedItems[indexPath.Row];
return cell;
}
@ -1086,10 +1110,7 @@ namespace Xamarin.Forms.Platform.iOS
if (selector == null)
return DefaultItemTemplateId;
var templatedList = TemplatedItemsView.TemplatedItems;
if (List.IsGroupingEnabled)
templatedList = (TemplatedItemsList<ItemsView<Cell>, Cell>)((IList)templatedList)[indexPath.Section];
var templatedList = GetTemplatedItemsListForPath(indexPath);
var item = templatedList.ListProxy[indexPath.Row];
itemTemplate = selector.SelectTemplate(item, List);

Просмотреть файл

@ -43,5 +43,29 @@
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="SelectDataTemplate">
<MemberSignature Language="C#" Value="public static Xamarin.Forms.DataTemplate SelectDataTemplate (this Xamarin.Forms.DataTemplate self, object item, Xamarin.Forms.BindableObject container);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.DataTemplate SelectDataTemplate(class Xamarin.Forms.DataTemplate self, object item, class Xamarin.Forms.BindableObject container) cil managed" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="self" Type="Xamarin.Forms.DataTemplate" RefType="this" />
<Parameter Name="item" Type="System.Object" />
<Parameter Name="container" Type="Xamarin.Forms.BindableObject" />
</Parameters>
<Docs>
<param name="self">To be added.</param>
<param name="item">To be added.</param>
<param name="container">To be added.</param>
<summary>To be added.</summary>
<returns>To be added.</returns>
<remarks>To be added.</remarks>
</Docs>
</Member>
</Members>
</Type>

Просмотреть файл

@ -558,6 +558,31 @@
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="SelectDataTemplate">
<MemberSignature Language="C#" Value="public Xamarin.Forms.DataTemplate SelectDataTemplate (object item);" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class Xamarin.Forms.DataTemplate SelectDataTemplate(object item) cil managed" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Attributes>
<Attribute>
<AttributeName>System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)</AttributeName>
</Attribute>
</Attributes>
<ReturnValue>
<ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="item" Type="System.Object" />
</Parameters>
<Docs>
<param name="item">To be added.</param>
<summary>To be added.</summary>
<returns>To be added.</returns>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="ShortName">
<MemberSignature Language="C#" Value="public string ShortName { get; set; }" />
<MemberSignature Language="ILAsm" Value=".property instance string ShortName" />

Просмотреть файл

@ -286,6 +286,26 @@
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="SelectDataTemplate">
<MemberSignature Language="C#" Value="public Xamarin.Forms.DataTemplate SelectDataTemplate (object item);" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class Xamarin.Forms.DataTemplate SelectDataTemplate(object item) cil managed" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="item" Type="System.Object" />
</Parameters>
<Docs>
<param name="item">To be added.</param>
<summary>To be added.</summary>
<returns>To be added.</returns>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="ShortNames">
<MemberSignature Language="C#" Value="public System.Collections.Generic.IReadOnlyList&lt;string&gt; ShortNames { get; }" />
<MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IReadOnlyList`1&lt;string&gt; ShortNames" />

Просмотреть файл

@ -9,6 +9,11 @@
<Base>
<BaseTypeName>System.Enum</BaseTypeName>
</Base>
<Attributes>
<Attribute>
<AttributeName>System.Flags</AttributeName>
</Attribute>
</Attributes>
<Docs>
<summary>Enumerates caching strategies for a ListView.</summary>
<remarks>
@ -48,6 +53,20 @@
<summary>Indicates that unneeded cells will have their binding contexts updated to that of a cell that is needed.</summary>
</Docs>
</Member>
<Member MemberName="RecycleElementAndDataTemplate">
<MemberSignature Language="C#" Value="RecycleElementAndDataTemplate" />
<MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ListViewCachingStrategy RecycleElementAndDataTemplate = int32(3)" />
<MemberType>Field</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>Xamarin.Forms.ListViewCachingStrategy</ReturnType>
</ReturnValue>
<Docs>
<summary>To be added.</summary>
</Docs>
</Member>
<Member MemberName="RetainElement">
<MemberSignature Language="C#" Value="RetainElement" />
<MemberSignature Language="ILAsm" Value=".field public static literal valuetype Xamarin.Forms.ListViewCachingStrategy RetainElement = int32(0)" />

Просмотреть файл

@ -1071,6 +1071,31 @@
<Link Type="Xamarin.Forms.Internals.DataTemplateExtensions" Member="M:Xamarin.Forms.Internals.DataTemplateExtensions.CreateContent(Xamarin.Forms.DataTemplate,System.Object,Xamarin.Forms.BindableObject)" />
</Member>
</ExtensionMethod>
<ExtensionMethod>
<Targets>
<Target Type="T:Xamarin.Forms.DataTemplate" />
</Targets>
<Member MemberName="SelectDataTemplate">
<MemberSignature Language="C#" Value="public static Xamarin.Forms.DataTemplate SelectDataTemplate (this Xamarin.Forms.DataTemplate self, object item, Xamarin.Forms.BindableObject container);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig class Xamarin.Forms.DataTemplate SelectDataTemplate(class Xamarin.Forms.DataTemplate self, object item, class Xamarin.Forms.BindableObject container) cil managed" />
<MemberType>ExtensionMethod</MemberType>
<ReturnValue>
<ReturnType>Xamarin.Forms.DataTemplate</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="self" Type="Xamarin.Forms.DataTemplate" RefType="this" />
<Parameter Name="item" Type="System.Object" />
<Parameter Name="container" Type="Xamarin.Forms.BindableObject" />
</Parameters>
<Docs>
<param name="self">To be added.</param>
<param name="item">To be added.</param>
<param name="container">To be added.</param>
<summary>To be added.</summary>
</Docs>
<Link Type="Xamarin.Forms.Internals.DataTemplateExtensions" Member="M:Xamarin.Forms.Internals.DataTemplateExtensions.SelectDataTemplate(Xamarin.Forms.DataTemplate,System.Object,Xamarin.Forms.BindableObject)" />
</Member>
</ExtensionMethod>
<ExtensionMethod>
<Targets>
<Target Type="T:Xamarin.Forms.Internals.DeviceOrientation" />