summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkingces95 <kingces95@users.noreply.github.com>2017-09-16 10:10:04 -0400
committerRui Marinho <me@ruimarinho.net>2017-09-16 15:13:02 +0100
commitf7d8cff6ae31c329f6049dcd0df795705369b674 (patch)
tree5f10ac71659fe11df88cafdf1a5239ec80d72dbe
parentc1095f45a994f5b8ba4e6ca6e44cccb3dffeef95 (diff)
downloadxamarin-forms-f7d8cff6ae31c329f6049dcd0df795705369b674.tar.gz
xamarin-forms-f7d8cff6ae31c329f6049dcd0df795705369b674.tar.bz2
xamarin-forms-f7d8cff6ae31c329f6049dcd0df795705369b674.zip
Add iOS prototypical cell cache for LV RowHeight calcs (#1143)
-rw-r--r--Xamarin.Forms.Core.UnitTests/DataTemplateSelectorTests.cs65
-rw-r--r--Xamarin.Forms.Core/DataTemplateExtensions.cs16
-rw-r--r--Xamarin.Forms.Core/DataTemplateSelector.cs32
-rw-r--r--Xamarin.Forms.Core/ElementTemplate.cs4
-rw-r--r--Xamarin.Forms.Core/ITemplatedItemsList.cs1
-rw-r--r--Xamarin.Forms.Core/ItemsView.cs13
-rw-r--r--Xamarin.Forms.Core/ListView.cs6
-rw-r--r--Xamarin.Forms.Core/ListViewCachingStrategy.cs6
-rw-r--r--Xamarin.Forms.Core/TemplatedItemsList.cs12
-rw-r--r--Xamarin.Forms.Platform.MacOS/Renderers/ListViewDataSource.cs2
-rw-r--r--Xamarin.Forms.Platform.iOS/ContextActionCell.cs12
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs151
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/DataTemplateExtensions.xml24
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/TemplatedItemsList`2.xml25
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ITemplatedItemsList`1.xml20
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ListViewCachingStrategy.xml19
-rw-r--r--docs/Xamarin.Forms.Core/index.xml25
17 files changed, 344 insertions, 89 deletions
diff --git a/Xamarin.Forms.Core.UnitTests/DataTemplateSelectorTests.cs b/Xamarin.Forms.Core.UnitTests/DataTemplateSelectorTests.cs
index 552f784b..d009a608 100644
--- a/Xamarin.Forms.Core.UnitTests/DataTemplateSelectorTests.cs
+++ b/Xamarin.Forms.Core.UnitTests/DataTemplateSelectorTests.cs
@@ -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]; });
+ }
+ }
} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DataTemplateExtensions.cs b/Xamarin.Forms.Core/DataTemplateExtensions.cs
index 3589fb01..34ee5941 100644
--- a/Xamarin.Forms.Core/DataTemplateExtensions.cs
+++ b/Xamarin.Forms.Core/DataTemplateExtensions.cs
@@ -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();
}
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/DataTemplateSelector.cs b/Xamarin.Forms.Core/DataTemplateSelector.cs
index 8ffa4781..7e284f7c 100644
--- a/Xamarin.Forms.Core/DataTemplateSelector.cs
+++ b/Xamarin.Forms.Core/DataTemplateSelector.cs
@@ -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);
diff --git a/Xamarin.Forms.Core/ElementTemplate.cs b/Xamarin.Forms.Core/ElementTemplate.cs
index 016dee7e..d7e842b5 100644
--- a/Xamarin.Forms.Core/ElementTemplate.cs
+++ b/Xamarin.Forms.Core/ElementTemplate.cs
@@ -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; }
diff --git a/Xamarin.Forms.Core/ITemplatedItemsList.cs b/Xamarin.Forms.Core/ITemplatedItemsList.cs
index be9055af..ded42597 100644
--- a/Xamarin.Forms.Core/ITemplatedItemsList.cs
+++ b/Xamarin.Forms.Core/ITemplatedItemsList.cs
@@ -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);
diff --git a/Xamarin.Forms.Core/ItemsView.cs b/Xamarin.Forms.Core/ItemsView.cs
index 33114f3c..4efa7221 100644
--- a/Xamarin.Forms.Core/ItemsView.cs
+++ b/Xamarin.Forms.Core/ItemsView.cs
@@ -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;
}
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/ListView.cs b/Xamarin.Forms.Core/ListView.cs
index 0a739416..ce6bc1cc 100644
--- a/Xamarin.Forms.Core/ListView.cs
+++ b/Xamarin.Forms.Core/ListView.cs
@@ -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;
}
diff --git a/Xamarin.Forms.Core/ListViewCachingStrategy.cs b/Xamarin.Forms.Core/ListViewCachingStrategy.cs
index 7dd90196..d45519a5 100644
--- a/Xamarin.Forms.Core/ListViewCachingStrategy.cs
+++ b/Xamarin.Forms.Core/ListViewCachingStrategy.cs
@@ -1,8 +1,12 @@
+using System;
+
namespace Xamarin.Forms
{
+ [Flags]
public enum ListViewCachingStrategy
{
RetainElement = 0,
- RecycleElement
+ RecycleElement = 1 << 0,
+ RecycleElementAndDataTemplate = RecycleElement | 1 << 1,
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Core/TemplatedItemsList.cs b/Xamarin.Forms.Core/TemplatedItemsList.cs
index 31823c8e..417947c8 100644
--- a/Xamarin.Forms.Core/TemplatedItemsList.cs
+++ b/Xamarin.Forms.Core/TemplatedItemsList.cs
@@ -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;
diff --git a/Xamarin.Forms.Platform.MacOS/Renderers/ListViewDataSource.cs b/Xamarin.Forms.Platform.MacOS/Renderers/ListViewDataSource.cs
index 1a9cf7f0..ecc67f6a 100644
--- a/Xamarin.Forms.Platform.MacOS/Renderers/ListViewDataSource.cs
+++ b/Xamarin.Forms.Platform.MacOS/Renderers/ListViewDataSource.cs
@@ -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)
diff --git a/Xamarin.Forms.Platform.iOS/ContextActionCell.cs b/Xamarin.Forms.Platform.iOS/ContextActionCell.cs
index 45f54340..1b0f5103 100644
--- a/Xamarin.Forms.Platform.iOS/ContextActionCell.cs
+++ b/Xamarin.Forms.Platform.iOS/ContextActionCell.cs
@@ -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
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
index 7fd68cc0..f6cccd54 100644
--- a/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
@@ -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;
-
- // 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 (_estimatedRowHeight)
+ return;
- 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()
+ {
+ _prototypicalCellByTypeOrDataTemplate.Clear();
+ }
+
+ internal Cell GetPrototypicalCell(NSIndexPath indexPath)
{
- if (_useEstimatedRowHeight)
- return tableView.EstimatedRowHeight;
+ var itemTypeOrDataTemplate = default(object);
+
+ 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);
- // 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;
- return UITableView.AutomaticDimension;
+ 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);
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/DataTemplateExtensions.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/DataTemplateExtensions.xml
index 9483388d..90f2f672 100644
--- a/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/DataTemplateExtensions.xml
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/DataTemplateExtensions.xml
@@ -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>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/TemplatedItemsList`2.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/TemplatedItemsList`2.xml
index cca38797..6d000dd8 100644
--- a/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/TemplatedItemsList`2.xml
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms.Internals/TemplatedItemsList`2.xml
@@ -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" />
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ITemplatedItemsList`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ITemplatedItemsList`1.xml
index a2418ea4..94bcbe67 100644
--- a/docs/Xamarin.Forms.Core/Xamarin.Forms/ITemplatedItemsList`1.xml
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ITemplatedItemsList`1.xml
@@ -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" />
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ListViewCachingStrategy.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ListViewCachingStrategy.xml
index 4aca0cf0..4eb2ba3a 100644
--- a/docs/Xamarin.Forms.Core/Xamarin.Forms/ListViewCachingStrategy.xml
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ListViewCachingStrategy.xml
@@ -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)" />
diff --git a/docs/Xamarin.Forms.Core/index.xml b/docs/Xamarin.Forms.Core/index.xml
index 16c1cfa1..1b13e335 100644
--- a/docs/Xamarin.Forms.Core/index.xml
+++ b/docs/Xamarin.Forms.Core/index.xml
@@ -1072,6 +1072,31 @@
</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" />
</Targets>
<Member MemberName="IsLandscape">