summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamantha Houts <samantha@teamredwall.com>2016-07-01 13:51:38 -0700
committerRui Marinho <me@ruimarinho.net>2016-07-01 21:51:38 +0100
commiteb84f968f2fac47c375724465854e58c85e45bee (patch)
tree64d9ded58234602c4bdea1e706db6e0f9ba90c3c
parent128796e6d0c6bc4c48ba3b6de4ca97a33d698724 (diff)
downloadxamarin-forms-eb84f968f2fac47c375724465854e58c85e45bee.tar.gz
xamarin-forms-eb84f968f2fac47c375724465854e58c85e45bee.tar.bz2
xamarin-forms-eb84f968f2fac47c375724465854e58c85e45bee.zip
[All] Crash fixes for ListViews (#243)
* [Controls] Add repro for 42277 * [Android] No crash if GroupHeaderTemplate=null * [Android] Fix DataTemplateSelector crash * [Core] Expose ListProxy on TIL * [iOS] Fix DataTemplateSelector crash * [Win] Fix DataTemplateSelector crash * [Docs] Update docs * [Core] Implement ListProxy explicitly Allows ListProxy property to stay internal. * [Controls] Revert unnecessary change to shproj
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla42277.cs121
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems1
-rw-r--r--Xamarin.Forms.Core/ITemplatedItemsList.cs2
-rw-r--r--Xamarin.Forms.Core/TemplatedItemsList.cs5
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs6
-rw-r--r--Xamarin.Forms.Platform.WinRT/ListViewRenderer.cs2
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs10
-rw-r--r--docs/Xamarin.Forms.Core/Xamarin.Forms/ITemplatedItemsList`1.xml16
8 files changed, 154 insertions, 9 deletions
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla42277.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla42277.cs
new file mode 100644
index 00000000..1a7624ae
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla42277.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Linq;
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+using System.Collections.Generic;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.Bugzilla, 42277, "DataTemplate System.InvalidCastException crash in 2.3.1-pre1")]
+ public class Bugzilla42277 : TestContentPage
+ {
+ const string Success1 = "Success1";
+ const string Success2 = "Success2";
+ const string Success3 = "GroupedSuccess3";
+ const string Success4 = "GroupedSuccess4";
+ const string Success5 = "GroupedSuccess5";
+ const string Success6 = "GroupedSuccess6";
+
+ class MyDataTemplateSelector : DataTemplateSelector
+ {
+ DataTemplate _1Template;
+ DataTemplate _2Template;
+
+ DataTemplate _3Template;
+ DataTemplate _4Template;
+ DataTemplate _5Template;
+ DataTemplate _6Template;
+
+ public MyDataTemplateSelector()
+ {
+ _1Template = new DataTemplate(() =>
+ {
+ return new TextCell { Text = Success1 };
+ });
+
+ _2Template = new DataTemplate(() =>
+ {
+ return new TextCell { Text = Success2 };
+ });
+
+ _3Template = new DataTemplate(() =>
+ {
+ return new TextCell { Text = Success3 };
+ });
+
+ _4Template = new DataTemplate(() =>
+ {
+ return new TextCell { Text = Success4 };
+ });
+
+ _5Template = new DataTemplate(() =>
+ {
+ return new TextCell { Text = Success5 };
+ });
+
+ _6Template = new DataTemplate(() =>
+ {
+ return new TextCell { Text = Success6 };
+ });
+ }
+
+ protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
+ {
+ int number = (int)item;
+ switch (number)
+ {
+ default:
+ case 0: return _1Template;
+ case 1: return _2Template;
+ case 2: return _3Template;
+ case 3: return _4Template;
+ case 4: return _5Template;
+ case 5: return _6Template;
+ }
+ }
+ }
+
+ protected override void Init()
+ {
+ //test non-grouped DTS
+ ListView listView = new ListView(ListViewCachingStrategy.RecycleElement)
+ {
+ ItemsSource = Enumerable.Range(0, 2),
+ ItemTemplate = new MyDataTemplateSelector()
+ };
+
+ //test grouped DTS
+ ListView groupedListView = new ListView(ListViewCachingStrategy.RecycleElement)
+ {
+ ItemsSource = new List<List<int>> { Enumerable.Range(2, 2).ToList(), Enumerable.Range(4, 2).ToList() },
+ IsGroupingEnabled = true,
+ ItemTemplate = new MyDataTemplateSelector()
+ };
+
+ Content = new StackLayout { Children = { listView, groupedListView } };
+
+ //test collection changed
+ listView.ItemsSource = Enumerable.Range(0, 2);
+ groupedListView.ItemsSource = new List<List<int>> { Enumerable.Range(2, 2).ToList(), Enumerable.Range(4, 2).ToList() };
+ }
+
+#if UITEST
+ [Test]
+ public void Bugzilla42277Test()
+ {
+ RunningApp.WaitForElement(q => q.Marked(Success1));
+ RunningApp.WaitForElement(q => q.Marked(Success2));
+ RunningApp.WaitForElement(q => q.Marked(Success3));
+ RunningApp.WaitForElement(q => q.Marked(Success4));
+ RunningApp.WaitForElement(q => q.Marked(Success5));
+ RunningApp.WaitForElement(q => q.Marked(Success6));
+ }
+#endif
+ }
+}
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
index 919d5062..10e0800c 100644
--- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
@@ -156,6 +156,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla39853.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TestPages\ScreenshotConditionalApp.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla41842.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla42277.cs" />
<Compile Include="$(MSBuildThisFileDirectory)_Template.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue1028.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue1075.cs" />
diff --git a/Xamarin.Forms.Core/ITemplatedItemsList.cs b/Xamarin.Forms.Core/ITemplatedItemsList.cs
index ae979d71..be9055af 100644
--- a/Xamarin.Forms.Core/ITemplatedItemsList.cs
+++ b/Xamarin.Forms.Core/ITemplatedItemsList.cs
@@ -17,6 +17,8 @@ namespace Xamarin.Forms
IEnumerable ItemsSource { get; }
IReadOnlyList<string> ShortNames { get; }
+ IListProxy ListProxy { get; }
+
int GetGlobalIndexForGroup(ITemplatedItemsList<TItem> group);
int GetGlobalIndexOfItem(object item);
ITemplatedItemsList<TItem> GetGroup(int index);
diff --git a/Xamarin.Forms.Core/TemplatedItemsList.cs b/Xamarin.Forms.Core/TemplatedItemsList.cs
index 75a0d394..cb64e2e9 100644
--- a/Xamarin.Forms.Core/TemplatedItemsList.cs
+++ b/Xamarin.Forms.Core/TemplatedItemsList.cs
@@ -194,6 +194,11 @@ namespace Xamarin.Forms
private set { SetValue(ListProxyPropertyKey, value); }
}
+ IListProxy ITemplatedItemsList<TItem>.ListProxy
+ {
+ get { return ListProxy; }
+ }
+
DataTemplate ItemTemplate
{
get { return (DataTemplate)_itemsView.GetValue(_itemTemplateProperty); }
diff --git a/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs b/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs
index 5ac214cd..2230d2b4 100644
--- a/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs
+++ b/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs
@@ -144,9 +144,9 @@ namespace Xamarin.Forms.Platform.Android
{
object item = null;
if (_listView.IsGroupingEnabled)
- item = ((ITemplatedItemsView<Cell>)TemplatedItemsView.TemplatedItems.GetGroup(group)).ListProxy[row];
+ item = TemplatedItemsView.TemplatedItems.GetGroup(group).ListProxy[row];
else
- item = ((ITemplatedItemsView<Cell>)TemplatedItemsView.TemplatedItems).ListProxy[position];
+ item = TemplatedItemsView.TemplatedItems.ListProxy[position];
itemTemplate = selector.SelectTemplate(item, _listView);
}
int key;
@@ -405,7 +405,7 @@ namespace Xamarin.Forms.Platform.Android
{
if (_listView.CachingStrategy == ListViewCachingStrategy.RecycleElement)
{
- var groupContent = _listView.TemplatedItems.GroupHeaderTemplate.CreateContent(group.ItemsSource, _listView) as Cell;
+ var groupContent = _listView.TemplatedItems.GroupHeaderTemplate?.CreateContent(group.ItemsSource, _listView) as Cell;
if (groupContent != null)
{
groupContent.Parent = _listView;
diff --git a/Xamarin.Forms.Platform.WinRT/ListViewRenderer.cs b/Xamarin.Forms.Platform.WinRT/ListViewRenderer.cs
index c6a9d2db..d6ec7038 100644
--- a/Xamarin.Forms.Platform.WinRT/ListViewRenderer.cs
+++ b/Xamarin.Forms.Platform.WinRT/ListViewRenderer.cs
@@ -287,7 +287,7 @@ namespace Xamarin.Forms.Platform.WinRT
if (Device.Idiom == TargetIdiom.Phone)
await Task.Delay(1);
- IListProxy listProxy = ((ITemplatedItemsView<Cell>)til).ListProxy;
+ IListProxy listProxy = til.ListProxy;
ScrollTo(listProxy.ProxiedEnumerable, listProxy[0], ScrollToPosition.Start, true, true);
}
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
index 238759e9..5483a169 100644
--- a/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
@@ -310,7 +310,7 @@ namespace Xamarin.Forms.Platform.iOS
void OnGroupedCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
- var til = (ITemplatedItemsList<Cell>)sender;
+ var til = (TemplatedItemsList<ItemsView<Cell>, Cell>)sender;
var templatedItems = TemplatedItemsView.TemplatedItems;
var groupIndex = templatedItems.IndexOf(til.HeaderContent);
@@ -919,7 +919,7 @@ namespace Xamarin.Forms.Platform.iOS
{
var templatedItems = TemplatedItemsView.TemplatedItems;
if (List.IsGroupingEnabled)
- templatedItems = (ITemplatedItemsList<Cell>)((IList)templatedItems)[indexPath.Section];
+ templatedItems = (TemplatedItemsList<ItemsView<Cell>, Cell>)((IList)templatedItems)[indexPath.Section];
var cell = templatedItems[indexPath.Row];
return cell;
@@ -934,7 +934,7 @@ namespace Xamarin.Forms.Platform.iOS
{
var currentSelected = _uiTableView.IndexPathForSelectedRow;
- var til = (ITemplatedItemsView<Cell>)sender;
+ var til = (TemplatedItemsList<ItemsView<Cell>, Cell>)sender;
var groupIndex = ((IList)TemplatedItemsView.TemplatedItems).IndexOf(til);
if (groupIndex == -1)
{
@@ -968,9 +968,9 @@ namespace Xamarin.Forms.Platform.iOS
var templatedList = TemplatedItemsView.TemplatedItems;
if (List.IsGroupingEnabled)
- templatedList = (ITemplatedItemsList<Cell>)((IList)templatedList)[indexPath.Section];
+ templatedList = (TemplatedItemsList<ItemsView<Cell>, Cell>)((IList)templatedList)[indexPath.Section];
- var item = ((ITemplatedItemsView<Cell>)templatedList).ListProxy[indexPath.Row];
+ var item = templatedList.ListProxy[indexPath.Row];
itemTemplate = selector.SelectTemplate(item, List);
int key;
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ITemplatedItemsList`1.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ITemplatedItemsList`1.xml
index d3e6f449..e526ffab 100644
--- a/docs/Xamarin.Forms.Core/Xamarin.Forms/ITemplatedItemsList`1.xml
+++ b/docs/Xamarin.Forms.Core/Xamarin.Forms/ITemplatedItemsList`1.xml
@@ -239,6 +239,22 @@
<remarks>To be added.</remarks>
</Docs>
</Member>
+ <Member MemberName="ListProxy">
+ <MemberSignature Language="C#" Value="public Xamarin.Forms.IListProxy ListProxy { get; }" />
+ <MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.IListProxy ListProxy" />
+ <MemberType>Property</MemberType>
+ <AssemblyInfo>
+ <AssemblyVersion>2.0.0.0</AssemblyVersion>
+ </AssemblyInfo>
+ <ReturnValue>
+ <ReturnType>Xamarin.Forms.IListProxy</ReturnType>
+ </ReturnValue>
+ <Docs>
+ <summary>To be added.</summary>
+ <value>To be added.</value>
+ <remarks>To be added.</remarks>
+ </Docs>
+ </Member>
<Member MemberName="Name">
<MemberSignature Language="C#" Value="public string Name { get; set; }" />
<MemberSignature Language="ILAsm" Value=".property instance string Name" />