From 17c7d8ed5c4c629b5a235bad4c66400e534f0615 Mon Sep 17 00:00:00 2001 From: Samantha Houts Date: Tue, 25 Apr 2017 11:14:16 -0700 Subject: [PATCH] [iOS] Prevent NRE in ListView OnItemSelected (#883) * Add repro * [iOS] Prevent NRE in ListView * [Android] Prevent NRE in ListView Not observed, but adding defensive check just in case --- .../ListViewNRE.cs | 51 ++++++++++++++++++++++ .../Xamarin.Forms.Controls.Issues.Shared.projitems | 3 +- .../Renderers/ListViewAdapter.cs | 3 ++ .../Renderers/ListViewRenderer.cs | 3 ++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ListViewNRE.cs diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ListViewNRE.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ListViewNRE.cs new file mode 100644 index 0000000..95d4338 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/ListViewNRE.cs @@ -0,0 +1,51 @@ +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; +using System.Linq; + +#if UITEST +using Xamarin.UITest; +using NUnit.Framework; +#endif + +// Apply the default category of "Issues" to all of the tests in this assembly +// We use this as a catch-all for tests which haven't been individually categorized +#if UITEST +[assembly: NUnit.Framework.Category("Issues")] +#endif + +namespace Xamarin.Forms.Controls.Issues +{ + [Preserve(AllMembers = true)] + [Issue(IssueTracker.None, 0, "ListView crashes when disposed on ItemSelected", PlatformAffected.iOS)] + public class ListViewNRE : TestContentPage + { + const string Success = "Success"; + + protected override void Init() + { + var listView = new ListView + { + ItemsSource = Enumerable.Range(0, 10) + }; + + listView.ItemSelected += ListView_ItemSelected; + + Content = listView; + } + + void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e) + { + Content = new Label { Text = Success }; + } + +#if UITEST + [Test] + public void ListViewNRETest() + { + RunningApp.WaitForElement(q => q.Marked("1")); + RunningApp.Tap(q => q.Marked("1")); + RunningApp.WaitForElement(q => q.Marked(Success)); + } +#endif + } +} \ No newline at end of file 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 70723f5..73f1bc2 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 @@ -275,6 +275,7 @@ + @@ -693,4 +694,4 @@ MSBuild:UpdateDesignTimeXaml - + \ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs b/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs index 4c9d231..17c7ffa 100644 --- a/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs +++ b/Xamarin.Forms.Platform.Android/Renderers/ListViewAdapter.cs @@ -514,6 +514,9 @@ namespace Xamarin.Forms.Platform.Android void SelectItem(object item) { + if (_listView == null) + return; + int position = TemplatedItemsView.TemplatedItems.GetGlobalIndexOfItem(item); AView view = null; if (position != -1) diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs index 2a20a67..d060e7f 100644 --- a/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs @@ -868,6 +868,9 @@ namespace Xamarin.Forms.Platform.iOS return; } + if (List == null) + return; + var location = TemplatedItemsView.TemplatedItems.GetGroupAndIndexOfItem(eventArg.SelectedItem); if (location.Item1 == -1 || location.Item2 == -1) { -- 2.7.4