This repository was archived by the owner on May 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[iOS] Unsubscribe CellPropertyChanged when SwitchCellRenderer is disposed #3518
Merged
Changes from 8 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
b6668f0
[Controls] Add repo of issue #3408
rmarinho 6668663
[iOS] Unsubscribe CellPropertyChanged when cell is disposed
rmarinho 37db298
[Controls] Add issue to project
rmarinho d1a3c32
[iOS] Introduce CellPropertyChange to CellTableViewCell to used by al…
rmarinho b0d1c3c
[Controls] Simplify Issue
PureWeen c16ed7e
[iOS] Remove PropertyChanged that was not used
rmarinho cd91ac5
[Controls] add check for null binding on template, add notes about is…
PureWeen 159df6b
[Controls] added reference to Android crash
PureWeen ad695a7
[iOS]Use existing PropertyChanged on ViewCelRenderer
rmarinho bfb31dc
[iOS] Keep the existing override so we don't break users
rmarinho 51b84dd
Update TextCellRenderer.cs
rmarinho 89314ff
Merge branch '3.2.0' into fix-3408
rmarinho fae09a0
update submodule
rmarinho 6ae70eb
Merge branch '3.2.0' into fix-3408
rmarinho 95027b5
Merge branch '3.2.0' into fix-3408
rmarinho File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
221 changes: 221 additions & 0 deletions
221
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3408.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
using Xamarin.Forms.CustomAttributes; | ||
using Xamarin.Forms.Internals; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using static Xamarin.Forms.Controls.Issues.Issue3408; | ||
|
||
#if UITEST | ||
using Xamarin.UITest; | ||
using NUnit.Framework; | ||
#endif | ||
|
||
namespace Xamarin.Forms.Controls.Issues | ||
{ | ||
// This may crash for you on Android if you click too many buttons | ||
// https://github.com/xamarin/Xamarin.Forms/issues/3603 | ||
[Preserve(AllMembers = true)] | ||
[Issue(IssueTracker.Github, 3408, "System.ObjectDisposedException: from SwitchCellRenderer when changing ItemSource", PlatformAffected.iOS)] | ||
public class Issue3408 : TestContentPage | ||
{ | ||
public static List<Recommendation> GetRecommendations(object e) | ||
{ | ||
switch (e) | ||
{ | ||
case List<RecommendationsViewModel> pc: return pc.First().Recommendations; | ||
case List<RecommendationsViewModel2> pc: return pc.First().Recommendations; | ||
default: return null; | ||
} | ||
} | ||
protected override void Init() | ||
{ | ||
|
||
var grd = new Grid(); | ||
|
||
var aacountListView = new ListView(); | ||
aacountListView.HasUnevenRows = true; | ||
aacountListView.ItemTemplate = new AccountDetailsDataTemplateSelector(); | ||
aacountListView.BindingContext = new List<RecommendationsViewModel> { new RecommendationsViewModel() }; | ||
|
||
aacountListView.SetBinding(ListView.ItemsSourceProperty, "."); | ||
var btn = new Button | ||
{ | ||
Text = "Change Source", | ||
AutomationId = "btn1", | ||
Command = new Command(() => | ||
{ | ||
aacountListView.BindingContext = new List<RecommendationsViewModel2> { new RecommendationsViewModel2() }; | ||
}) | ||
}; | ||
var btn2 = new Button | ||
{ | ||
Text = "Change Property", | ||
AutomationId = "btn2", | ||
Command = new Command(() => | ||
{ | ||
|
||
foreach (var item in GetRecommendations(aacountListView.BindingContext)) | ||
{ | ||
item.Name = "New Item Name"; | ||
item.IsBusy = !item.IsBusy; | ||
} | ||
|
||
}) | ||
}; | ||
grd.Children.Add(aacountListView); | ||
Grid.SetRow(aacountListView, 0); | ||
grd.Children.Add(btn); | ||
Grid.SetRow(btn, 1); | ||
grd.Children.Add(btn2); | ||
Grid.SetRow(btn2, 2); | ||
Content = grd; | ||
} | ||
|
||
#if UITEST | ||
[Test] | ||
public void Issue3408Test () | ||
{ | ||
RunningApp.WaitForElement (q => q.Marked ("btn1")); | ||
RunningApp.WaitForElement (q => q.Marked ("Click to Change")); | ||
RunningApp.Tap(q => q.Marked("btn1")); | ||
RunningApp.WaitForElement(q => q.Marked("This should have changed")); | ||
RunningApp.Tap(q => q.Marked("btn2")); | ||
RunningApp.WaitForElement(q => q.Marked("New Item Name")); | ||
} | ||
#endif | ||
|
||
[Preserve(AllMembers = true)] | ||
public class RecommendationsBaseViewModel : ViewModelBase | ||
{ | ||
public string AccountName => $""; | ||
public List<Recommendation> Recommendations { get; set; } | ||
} | ||
|
||
[Preserve(AllMembers = true)] | ||
public class RecommendationsViewModel : RecommendationsBaseViewModel | ||
{ | ||
public string AccountName => $"Recommendations"; | ||
|
||
public RecommendationsViewModel() | ||
{ | ||
Recommendations = new List<Recommendation>() | ||
{ | ||
new Recommendation(){ Name = "Click to Change"} , | ||
new Recommendation(){ Name = "Recommendations"} , | ||
new Recommendation(){ Name = "Recommendations"} , | ||
}; | ||
} | ||
} | ||
|
||
[Preserve(AllMembers = true)] | ||
public class RecommendationsViewModel2 : RecommendationsBaseViewModel | ||
{ | ||
public string AccountName => $"Recommendations 2"; | ||
public RecommendationsViewModel2() | ||
{ | ||
Recommendations = new List<Recommendation>() | ||
{ | ||
new Recommendation(){ Name = "This should have changed"} , | ||
new Recommendation(){ Name = "Recommendations 2"} , | ||
new Recommendation(){ Name = "Recommendations 2", IsBusy = true } , | ||
}; | ||
} | ||
} | ||
|
||
[Preserve(AllMembers = true)] | ||
public class Recommendation : ViewModelBase | ||
{ | ||
string _name; | ||
public string Name | ||
{ | ||
get { return _name; } | ||
set | ||
{ | ||
if (_name == value) | ||
return; | ||
_name = value; | ||
OnPropertyChanged(); | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
[Preserve(AllMembers = true)] | ||
public class RecommendationsView : ContentView | ||
{ | ||
public RecommendationsView() | ||
{ | ||
Grid grd = new Grid(); | ||
var lst = new ListView | ||
{ | ||
ItemTemplate = new DataTemplate(() => | ||
{ | ||
var swittch = new SwitchCell(); | ||
swittch.SetBinding(SwitchCell.TextProperty, new Binding("Name")); | ||
swittch.SetBinding(SwitchCell.OnProperty, new Binding("IsBusy")); | ||
return swittch; | ||
}) | ||
|
||
}; | ||
|
||
lst.SetBinding(ListView.ItemsSourceProperty, new Binding("Recommendations")); | ||
grd.Children.Add(lst); | ||
Content = grd; | ||
} | ||
|
||
// This work around exists because of this issue | ||
// https://github.com/xamarin/Xamarin.Forms/issues/3602 | ||
object context = null; | ||
protected override void OnBindingContextChanged() | ||
{ | ||
base.OnBindingContextChanged(); | ||
if (BindingContext == null) | ||
Device.BeginInvokeOnMainThread(() => BindingContext = context); | ||
else | ||
context = BindingContext; | ||
} | ||
} | ||
|
||
[Preserve(AllMembers = true)] | ||
public class AccountDetailsDataTemplateSelector : DataTemplateSelector | ||
{ | ||
public Lazy<DataTemplate> RecommendationsViewDataTemplate { get; } | ||
public Lazy<ViewCell> RecommendationsView { get; } | ||
|
||
public Lazy<DataTemplate> RecommendationsViewDataTemplate2 { get; } | ||
public Lazy<ViewCell> RecommendationsView2 { get; } | ||
|
||
public AccountDetailsDataTemplateSelector() | ||
{ | ||
RecommendationsView = new Lazy<ViewCell>(() => new ViewCell() { View = new RecommendationsView() }); | ||
RecommendationsViewDataTemplate = new Lazy<DataTemplate>(() => new DataTemplate(() => RecommendationsView.Value)); | ||
|
||
|
||
RecommendationsView2 = new Lazy<ViewCell>(() => new ViewCell() { View = new RecommendationsView() }); | ||
RecommendationsViewDataTemplate2 = new Lazy<DataTemplate>(() => new DataTemplate(() => RecommendationsView2.Value)); | ||
} | ||
|
||
protected override DataTemplate OnSelectTemplate(object item, BindableObject container) | ||
{ | ||
if (item == null) | ||
{ | ||
return null; | ||
} | ||
|
||
if (item is RecommendationsViewModel) | ||
{ | ||
RecommendationsView.Value.BindingContext = item; | ||
return RecommendationsViewDataTemplate.Value; | ||
} | ||
|
||
if (item is RecommendationsViewModel2) | ||
{ | ||
RecommendationsView2.Value.BindingContext = item; | ||
return RecommendationsViewDataTemplate2.Value; | ||
} | ||
|
||
throw new ArgumentException("Invalid ViewModel Type"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ namespace Xamarin.Forms.Platform.iOS | |
public class CellTableViewCell : UITableViewCell, INativeElementView | ||
{ | ||
Cell _cell; | ||
public Action<object, PropertyChangedEventArgs> PropertyChanged; | ||
public Action<object, PropertyChangedEventArgs> CellPropertyChanged; | ||
bool _disposed; | ||
|
||
public CellTableViewCell(UITableViewCellStyle style, string key) : base(style, key) | ||
|
@@ -23,22 +23,26 @@ public Cell Cell | |
return; | ||
|
||
if (_cell != null) | ||
{ | ||
_cell.PropertyChanged -= HandleCellPropertyChanged; | ||
Device.BeginInvokeOnMainThread(_cell.SendDisappearing); | ||
|
||
} | ||
this._cell = value; | ||
_cell = value; | ||
|
||
if (_cell != null) | ||
{ | ||
_cell.PropertyChanged += HandleCellPropertyChanged; | ||
Device.BeginInvokeOnMainThread(_cell.SendAppearing); | ||
} | ||
} | ||
} | ||
|
||
public Element Element => Cell; | ||
|
||
public void HandlePropertyChanged(object sender, PropertyChangedEventArgs e) | ||
public void HandleCellPropertyChanged(object sender, PropertyChangedEventArgs e) | ||
{ | ||
if (PropertyChanged != null) | ||
PropertyChanged(this, e); | ||
CellPropertyChanged?.Invoke(sender, e); | ||
} | ||
|
||
internal static UITableViewCell GetNativeCell(UITableView tableView, Cell cell, bool recycleCells = false, string templateId = "") | ||
|
@@ -101,7 +105,11 @@ protected override void Dispose(bool disposing) | |
|
||
if (disposing) | ||
{ | ||
PropertyChanged = null; | ||
CellPropertyChanged = null; | ||
if (_cell != null) | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no braces needed |
||
_cell.PropertyChanged -= HandleCellPropertyChanged; | ||
} | ||
_cell = null; | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are both of these needed?