Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Add check if View is not disposed to prevent NRE for Android Button #14760

Merged
merged 2 commits into from
Oct 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
using System;
using System.Collections.ObjectModel;
using NUnit.Framework;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;

namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 14757, "[Bug] Android ObjectDisposedException thrown Button inside CollectionView with Binding", PlatformAffected.Android)]
public class Issue14757 : TestContentPage
{
public ObservableCollection<int> Values { get; set; } = new ObservableCollection<int>();

public static readonly BindableProperty SomeTextProperty = BindableProperty.Create(nameof(SomeText), typeof(string), typeof(Issue14757), default(string));
public string SomeText
{
get { return (string)GetValue(SomeTextProperty); }
set { SetValue(SomeTextProperty, value); }
}

public Issue14757()
{
SomeText = "Default";

for (int i = 0; i <= 1000; i++)
Values.Add(i);

BindingContext = this;
}

const string LabelAutomationId = "TheStatusLabel";
const string GoToPageAutomationId = "GoToPageButton";
const string ChangeTextAutomationId = "ChangeTextButton";

protected override void Init()
{
var statusLabel = new Label()
{
AutomationId = LabelAutomationId
};
statusLabel.SetBinding(Label.TextProperty, new Binding("SomeText"));

var button1 = new Button
{
Text = "To testpage",
AutomationId = GoToPageAutomationId
};
button1.Clicked += Button1_Clicked;

var button2 = new Button
{
Text = "Change Text",
AutomationId = ChangeTextAutomationId
};
button2.Clicked += Button2_Clicked;

var stackLayout = new StackLayout
{
Children = {
statusLabel,
button1,
button2
}
};

Content = stackLayout;
}

private void Button2_Clicked(object sender, EventArgs e)
{
SomeText = SomeText == "Default" ? "Some Value" : "Default";
}

private async void Button1_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new NewPage(this));
}

class NewPage : ContentPage
{
public Issue14757 MyMainPage { get; set; }

public NewPage(Issue14757 mainpage)
{
BindingContext = MyMainPage = mainpage;

var dataTemplate = new DataTemplate(() =>
{
var button = new Button();
button.SetBinding(Button.TextProperty, new Binding("SomeText", source: MyMainPage));
var stackLayout = new StackLayout
{
Children =
{
button
}
};
return stackLayout;
});

var collectionView = new CollectionView();
collectionView.SetBinding(CollectionView.ItemsSourceProperty, new Binding("Values"));
collectionView.ItemTemplate = dataTemplate;

var stackLayout = new StackLayout
{
Children =
{
collectionView
}
};

Content = stackLayout;
}
}

#if UITEST
[Test]
public void Issue14757Test()
{
System.Threading.Tasks.Task.Delay(500);

RunningApp.WaitForElement(LabelAutomationId);

for (int i = 0; i <= 10; i++)
{
RunningApp.Tap(GoToPageAutomationId);
System.Threading.Tasks.Task.Delay(500);
RunningApp.Back();
}

RunningApp.Tap(ChangeTextAutomationId);
RunningApp.WaitForElement("Some Value");
}
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1808,6 +1808,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Issue14505.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue14505-II.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue6387.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue14757.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml">
Expand Down Expand Up @@ -2902,7 +2903,7 @@
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue14095.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion Xamarin.Forms.Platform.Android/ButtonLayoutManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ void UpdatePadding()
bool UpdateTextAndImage()
{

if (_disposed || _renderer?.View == null || _element == null)
if (_disposed || _renderer?.View == null || _element == null || (View?.IsDisposed() ?? true))
return false;

if (View?.LayoutParameters == null && _hasLayoutOccurred)
Expand Down