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

Commit

Permalink
[iOS] Cannot access a disposed object using CollectionView EmptyView (#…
Browse files Browse the repository at this point in the history
…12923) fixes #12910 fixes #12894

* Added repro sample

* Updated sample

* Updated repro sample

* Fix build error
  • Loading branch information
jsuarezruiz committed Dec 11, 2020
1 parent db7ca13 commit 15fc853
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8" ?>
<controls:TestContentPage
xmlns:controls="clr-namespace:Xamarin.Forms.Controls"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Xamarin.Forms.Controls.Issues.Issue12910"
xmlns:local="clr-namespace:Xamarin.Forms.Controls.Issues"
Title="Issue 12910">
<ContentPage.Content>
<Grid
RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label
Padding="12"
BackgroundColor="Black"
TextColor="White"
Text="Pull to Refresh. Without exceptions, the test has passed."/>
<RefreshView
Grid.Row="1"
x:DataType="local:Issue12910ViewModel"
Command="{Binding LoadItemsCommand}"
IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
<CollectionView
x:Name="ItemsListView"
ItemsSource="{Binding Items}"
SelectionMode="None">
<CollectionView.ItemsLayout>
<GridItemsLayout
Orientation="Vertical"
HorizontalItemSpacing="10"
VerticalItemSpacing="10">
<GridItemsLayout.Span>
<OnIdiom
x:TypeArguments="x:Int32"
Default="2"
Tablet="4"
Desktop="6"/>
</GridItemsLayout.Span>
</GridItemsLayout>
</CollectionView.ItemsLayout>
<CollectionView.Header>
<ScrollView
Orientation="Horizontal"
HorizontalScrollBarVisibility="Never">
<StackLayout
Orientation="Horizontal"
Spacing="0"
BindableLayout.ItemsSource="{Binding Items}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Button
Text="{Binding Text}"
BackgroundColor="#555555"
Command="{Binding Source={RelativeSource AncestorType={x:Type local:Issue12910ViewModel}}, Path=ItemTapped}"
CommandParameter="{Binding .}"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ScrollView>
</CollectionView.Header>
<CollectionView.EmptyView>
<StackLayout>
<Label
HorizontalOptions="CenterAndExpand"
Text="Empty list"
VerticalOptions="EndAndExpand" />
<Button
Command="{Binding LoadItemsCommand}"
HorizontalOptions="CenterAndExpand"
Text="Refresh"
VerticalOptions="StartAndExpand" />
</StackLayout>
</CollectionView.EmptyView>
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame
CornerRadius="15"
Padding="15"
x:DataType="model:Item">
<StackLayout>
<Label
Text="{Binding Text}"
LineBreakMode="TailTruncation" />
<Label
Text="{Binding Description}"
LineBreakMode="TailTruncation" />
</StackLayout>
<Frame.GestureRecognizers>
<TapGestureRecognizer
NumberOfTapsRequired="1"
Command="{Binding Source={RelativeSource AncestorType={x:Type local:Issue12910ViewModel}}, Path=ItemTapped}"
CommandParameter="{Binding .}">
</TapGestureRecognizer>
</Frame.GestureRecognizers>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
</Grid>
</ContentPage.Content>
</controls:TestContentPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using System;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Threading.Tasks;
using System.Diagnostics;

#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
using Xamarin.Forms.Core.UITests;
#endif

namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.CollectionView)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 12910,
"[Bug] 'Cannot access a disposed object. Object name: 'DefaultRenderer' - on ios with CollectionView and EmptyView",
PlatformAffected.iOS)]
public partial class Issue12910 : TestContentPage
{
readonly Issue12910ViewModel _viewModel;

public Issue12910()
{
_viewModel = new Issue12910ViewModel();
#if APP
InitializeComponent();
BindingContext = _viewModel;
#endif
}

protected override void Init()
{

}

protected override void OnAppearing()
{
base.OnAppearing();
_viewModel.OnAppearing();
}
}

public class Issue12910Model
{
public string Id { get; set; }
public string Text { get; set; }
public string Description { get; set; }
}

public class Issue12910ViewModel : BindableObject
{
bool _isBusy;
Issue12910Model _selectedItem;

public ObservableCollection<Issue12910Model> Items { get; }
public Command LoadItemsCommand { get; }
public Command AddItemCommand { get; }
public Command<Issue12910Model> ItemTapped { get; }

public Issue12910ViewModel()
{
Items = new ObservableCollection<Issue12910Model>();
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
ItemTapped = new Command<Issue12910Model>(OnItemSelected);
AddItemCommand = new Command(OnAddItem);
}

async Task ExecuteLoadItemsCommand()
{
IsBusy = true;

try
{
Items.Clear();

await Task.Delay(500);

Items.Add(new Issue12910Model { Id = "1", Text = "Text 1", Description = "Description 1" });
Items.Add(new Issue12910Model { Id = "2", Text = "Text 2", Description = "Description 2" });
Items.Add(new Issue12910Model { Id = "3", Text = "Text 3", Description = "Description 3" });
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}

public void OnAppearing()
{
IsBusy = true;
SelectedItem = null;
}

public bool IsBusy
{
get => _isBusy;
set
{
_isBusy = value;
OnPropertyChanged();
}
}

public Issue12910Model SelectedItem
{
get => _selectedItem;
set
{
_selectedItem = value;
OnPropertyChanged();
}
}

void OnAddItem(object obj)
{

}

void OnItemSelected(Issue12910Model item)
{

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1653,6 +1653,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Issue12777.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue11911.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue11691.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue12910.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue8988.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue12084.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue12512.cs" />
Expand Down Expand Up @@ -2006,6 +2007,9 @@
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue11691.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue12910.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue12084.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
Expand Down
2 changes: 1 addition & 1 deletion Xamarin.Forms.Platform.iOS/VisualElementRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public override bool CanBecomeFirstResponder
{
get
{
if (Element.IsSet(PlatformConfiguration.iOSSpecific.VisualElement.CanBecomeFirstResponderProperty))
if (Element != null && Element.IsSet(PlatformConfiguration.iOSSpecific.VisualElement.CanBecomeFirstResponderProperty))
return PlatformConfiguration.iOSSpecific.VisualElement.GetCanBecomeFirstResponder(Element);

return base.CanBecomeFirstResponder;
Expand Down

0 comments on commit 15fc853

Please sign in to comment.