From 244ee01cfa3405c01746d9419e9955e07ae9df2e Mon Sep 17 00:00:00 2001 From: Rui Marinho Date: Tue, 5 Apr 2016 08:46:22 +0100 Subject: [PATCH] =?utf8?q?[iOS]=C2=A0Fix=20WeakNotifyCollectionChanged=20o?= =?utf8?q?n=20CarouselView?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Make some changes on WeakNotifyCollectionChanged to make it work ok in IOS, following the ListProxy approach. --- .../Bugzilla39499.cs | 64 +++++++++++++++++----- Xamarin.Forms.Core/ItemsViewSimple.cs | 31 ++++++----- 2 files changed, 67 insertions(+), 28 deletions(-) diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39499.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39499.cs index 1597ba8..16c033d 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39499.cs +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39499.cs @@ -30,6 +30,8 @@ namespace Xamarin.Forms.Controls } public int Id => id; + + public string Text => $"Item {Id}"; } [Preserve(AllMembers = true)] @@ -38,13 +40,13 @@ namespace Xamarin.Forms.Controls public ItemView() { var idLabel = new Label() { StyleId = "id", TextColor = Color.White }; - idLabel.SetBinding(Label.TextProperty, nameof(Item.Id)); + idLabel.SetBinding(Label.TextProperty, nameof(Item.Text)); var stackLayout = new StackLayout { Children = { - //new Label { Text = "Target" }, - //new Label { Text = "Stack" } + new Label { Text = "Target" }, + new Label { Text = "Stack" } }, BackgroundColor = Color.Red }; @@ -116,17 +118,38 @@ namespace Xamarin.Forms.Controls { Orientation = StackOrientation.Horizontal, HorizontalOptions = LayoutOptions.FillAndExpand, - Children = { - CreateButton ("<<", () => carouselView.Position = 0), - CreateButton ("<", () => { try { carouselView.Position--; } catch { } }), - CreateButton (">", () => { try { carouselView.Position++; } catch { } }), - CreateButton (">>", () => carouselView.Position = Items.Count - 1) - } + Children = + { + CreateButton("+", () => Items.Add(new Item())), + CreateButton("<<", () => carouselView.Position = 0), + CreateButton("<", () => + { + try + { + carouselView.Position--; + } + catch + { + } + }), + CreateButton(">", () => + { + try + { + carouselView.Position++; + } + catch + { + } + }), + CreateButton(">>", () => carouselView.Position = Items.Count - 1) + } }; Content = new StackLayout { - Children = { + Children = + { carouselView, moveBar } @@ -135,13 +158,26 @@ namespace Xamarin.Forms.Controls #if UITEST //[Test] - public void CarouselViewTest () + public void CarouselViewTest() { var app = RunningApp; - app.Screenshot ("I am at Issue 1"); - app.WaitForElement (q => q.Marked ("Remove")); + app.WaitForElement(q => q.Marked("Item 0")); + app.SwipeRightToLeft(); + app.WaitForElement(q => q.Marked("Item 1")); + app.Tap(c => c.Marked("<")); + app.WaitForElement(q => q.Marked("Item 0")); + } - app.Screenshot ("I see the Label"); + [Test] + public void CarouselViewTestAddItem() + { + var app = RunningApp; + app.WaitForElement(q => q.Marked("Hide Target Stack")); + app.Tap(c => c.Marked("+")); + app.SwipeRightToLeft(); + app.SwipeRightToLeft(); + app.WaitForElement(q => q.Marked("Item 2")); + app.Screenshot("I see the Item 2"); } #endif } diff --git a/Xamarin.Forms.Core/ItemsViewSimple.cs b/Xamarin.Forms.Core/ItemsViewSimple.cs index fd63183..34b7726 100644 --- a/Xamarin.Forms.Core/ItemsViewSimple.cs +++ b/Xamarin.Forms.Core/ItemsViewSimple.cs @@ -73,7 +73,7 @@ namespace Xamarin.Forms var dynamicItemSource = _itemSource as INotifyCollectionChanged; if (dynamicItemSource != null) { - new WeakNotifyCollectionChanged(dynamicItemSource, OnCollectionChange); + new WeakNotifyCollectionChanged(this, dynamicItemSource); } } @@ -82,34 +82,37 @@ namespace Xamarin.Forms internal event NotifyCollectionChangedEventHandler CollectionChanged; - void OnCollectionChange(object sender, NotifyCollectionChangedEventArgs e) + internal void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { CollectionChanged?.Invoke(sender, e); } sealed class WeakNotifyCollectionChanged { - readonly INotifyCollectionChanged _source; - // prevent the itemSource from keeping the itemsView alive - readonly WeakReference _weakTarget; + readonly WeakReference _weakCollection; + readonly WeakReference _weakSource; - public WeakNotifyCollectionChanged(INotifyCollectionChanged source, NotifyCollectionChangedEventHandler target) + public WeakNotifyCollectionChanged(ItemsView source, INotifyCollectionChanged incc) { - _weakTarget = new WeakReference(target); - _source = source; - _source.CollectionChanged += OnCollectionChanged; + incc.CollectionChanged += OnCollectionChanged; + + _weakSource = new WeakReference(source); + _weakCollection = new WeakReference(incc); } - public void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - NotifyCollectionChangedEventHandler weakTarget; - if (!_weakTarget.TryGetTarget(out weakTarget)) + ItemsView source; + if (!_weakSource.TryGetTarget(out source)) { - _source.CollectionChanged -= OnCollectionChanged; + INotifyCollectionChanged collection; + if (_weakCollection.TryGetTarget(out collection)) + collection.CollectionChanged -= OnCollectionChanged; + return; } - weakTarget(sender, e); + source.OnCollectionChanged(sender, e); } } -- 2.7.4