[iOS] Fix WeakNotifyCollectionChanged on CarouselView
authorRui Marinho <me@ruimarinho.net>
Tue, 5 Apr 2016 07:46:22 +0000 (08:46 +0100)
committerJason Smith <jason.smith@xamarin.com>
Tue, 5 Apr 2016 07:46:22 +0000 (00:46 -0700)
Make some changes on WeakNotifyCollectionChanged to make it work ok in IOS, following the ListProxy approach.

Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla39499.cs
Xamarin.Forms.Core/ItemsViewSimple.cs

index 1597ba8..16c033d 100644 (file)
@@ -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
        }
index fd63183..34b7726 100644 (file)
@@ -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<NotifyCollectionChangedEventHandler> _weakTarget;
+                       readonly WeakReference<INotifyCollectionChanged> _weakCollection;
+                       readonly WeakReference<ItemsView> _weakSource;
 
-                       public WeakNotifyCollectionChanged(INotifyCollectionChanged source, NotifyCollectionChangedEventHandler target)
+                       public WeakNotifyCollectionChanged(ItemsView source, INotifyCollectionChanged incc)
                        {
-                               _weakTarget = new WeakReference<NotifyCollectionChangedEventHandler>(target);
-                               _source = source;
-                               _source.CollectionChanged += OnCollectionChanged;
+                               incc.CollectionChanged += OnCollectionChanged;
+
+                               _weakSource = new WeakReference<ItemsView>(source);
+                               _weakCollection = new WeakReference<INotifyCollectionChanged>(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);
                        }
                }