summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core.UnitTests/TemplatedItemsListTests.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Core.UnitTests/TemplatedItemsListTests.cs')
-rw-r--r--Xamarin.Forms.Core.UnitTests/TemplatedItemsListTests.cs1073
1 files changed, 1073 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core.UnitTests/TemplatedItemsListTests.cs b/Xamarin.Forms.Core.UnitTests/TemplatedItemsListTests.cs
new file mode 100644
index 00000000..d723b660
--- /dev/null
+++ b/Xamarin.Forms.Core.UnitTests/TemplatedItemsListTests.cs
@@ -0,0 +1,1073 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Core.UnitTests
+{
+ [TestFixture]
+ public class TemplatedItemsListTests : BaseTestFixture
+ {
+ class MockItemsView
+ : ItemsView<BindableObject>
+ {
+ public MockItemsView()
+ {
+ TemplatedItems.IsGroupingEnabledProperty = IsGroupingEnabledProperty;
+ }
+
+ public event Action<BindableObject> Hooked;
+ public event Action<BindableObject> Unhooked;
+
+ public static readonly BindableProperty IsGroupingEnabledProperty =
+ BindableProperty.Create<MockItemsView, bool> (lv => lv.IsGroupingEnabled, false);
+
+ public bool IsGroupingEnabled
+ {
+ get { return (bool)GetValue (IsGroupingEnabledProperty); }
+ set { SetValue (IsGroupingEnabledProperty, value); }
+ }
+
+ protected override BindableObject CreateDefault (object item)
+ {
+ return new TextCell { Text = item.ToString () };
+ }
+
+ public new TemplatedItemsList<ItemsView<BindableObject>, BindableObject> TemplatedItems
+ {
+ get { return base.TemplatedItems; }
+ }
+
+ BindingBase groupShortNameBinding;
+ public BindingBase GroupShortNameBinding
+ {
+ get { return groupShortNameBinding; }
+ set {
+ if (groupShortNameBinding == value)
+ return;
+ OnPropertyChanging ();
+ groupShortNameBinding = value;
+ TemplatedItems.GroupShortNameBinding = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ BindingBase groupDisplayBinding;
+ public BindingBase GroupDisplayBinding
+ {
+ get { return groupDisplayBinding; }
+ set {
+ if (groupDisplayBinding == value)
+ return;
+
+ OnPropertyChanging ();
+ groupDisplayBinding = value;
+ TemplatedItems.GroupDisplayBinding = value;
+ OnPropertyChanged ();
+ }
+ }
+
+ protected override void SetupContent (BindableObject content, int index)
+ {
+ base.SetupContent (content, index);
+
+ if (Hooked != null)
+ Hooked (content);
+ }
+
+ protected override void UnhookContent (BindableObject content)
+ {
+ base.UnhookContent (content);
+
+ if (Unhooked != null)
+ Unhooked (content);
+ }
+ }
+
+ [SetUp]
+ public override void Setup()
+ {
+ base.Setup ();
+ bindable = new MockItemsView();
+
+ Device.PlatformServices = new MockPlatformServices ();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown ();
+ Device.PlatformServices = null;
+ }
+
+ MockItemsView bindable;
+
+ [Test]
+ public void ListProxyNotNullWithNullItemsSource()
+ {
+ Assert.IsNotNull (bindable.TemplatedItems.ListProxy);
+ }
+
+ [Test]
+ public void ResetOnItemsSourceChanged()
+ {
+ bool raised = false;
+ NotifyCollectionChangedAction action = default(NotifyCollectionChangedAction);
+ bindable.TemplatedItems.CollectionChanged += (sender, args) => {
+ raised = true;
+ action = args.Action;
+ };
+
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, Enumerable.Empty<string>());
+
+ Assert.IsTrue (raised, "CollectionChanged was not raised");
+ Assert.AreEqual (NotifyCollectionChangedAction.Reset, action);
+ }
+ /*
+ [Test]
+ public void ResetOnInfiniteScrollingChanged()
+ {
+ bool raised = false;
+ NotifyCollectionChangedAction action = default(NotifyCollectionChangedAction);
+ bindable.TemplatedItems.CollectionChanged += (sender, args) => {
+ raised = true;
+ action = args.Action;
+ };
+
+ bindable.SetValue (ItemsView.InfiniteScrollingProperty, true);
+
+ Assert.IsTrue (raised, "CollectionChanged was not raised");
+ Assert.AreEqual (NotifyCollectionChangedAction.Reset, action);
+ }*/
+
+ [Test]
+ public void ResetOnTemplateChanged()
+ {
+ // Template changes won't trigger a reset if there's no items.
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, new[] { "Foo" });
+
+ bool raised = false;
+ NotifyCollectionChangedAction action = default(NotifyCollectionChangedAction);
+ bindable.TemplatedItems.CollectionChanged += (sender, args) => {
+ raised = true;
+ action = args.Action;
+ };
+
+ bindable.SetValue (ItemsView<BindableObject>.ItemTemplateProperty, new DataTemplate());
+
+ Assert.IsTrue (raised, "CollectionChanged was not raised");
+ Assert.AreEqual (NotifyCollectionChangedAction.Reset, action);
+ }
+
+ [Test]
+ public void PassThroughChanges()
+ {
+ var collection = new ObservableCollection<string>();
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ bool raised = false;
+ NotifyCollectionChangedEventArgs args = null;
+ bindable.TemplatedItems.CollectionChanged += (sender, eventArgs) => {
+ raised = true;
+ args = eventArgs;
+ };
+
+ string str = "foo bar";
+ collection.Add (str);
+
+ Assert.IsTrue (raised, "CollectionChanged was not raised");
+ Assert.AreEqual (NotifyCollectionChangedAction.Add, args.Action);
+ Assert.AreEqual (0, args.NewStartingIndex);
+ Assert.IsNotNull (args.NewItems);
+ Assert.AreEqual (1, args.NewItems.Count);
+ Assert.AreSame (str, ((Cell)args.NewItems[0]).BindingContext);
+ }
+
+ [Test]
+ public void ListProxyUpdatesWithItemsSource()
+ {
+ var collection = new List<string> { "foo bar" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ Assert.IsNotNull (bindable.TemplatedItems.ListProxy);
+ Assert.AreEqual (collection.Count, bindable.TemplatedItems.ListProxy.Count);
+ }
+
+ [Test]
+ public void GetOrCreateContent ([Values (0, 1, 2)] int index)
+ {
+ var collection = new List<string> { "foo", "bar", "baz" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ DataTemplate template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, new Binding ("."));
+ bindable.SetValue (ItemsView<BindableObject>.ItemTemplateProperty, template);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.IsNotNull (content);
+
+ TextCell textCell = content as TextCell;
+ Assert.IsNotNull (textCell, "Content was did not match the template type, expected {0} but got {1}", typeof(TextCell), content.GetType());
+
+ Assert.AreSame (collection[index], textCell.BindingContext);
+ Assert.AreSame (collection[index], textCell.Text);
+
+ BindableObject content2 = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.AreSame (content, content2);
+ }
+
+ [Test]
+ public void GetOrCreateContentDefault()
+ {
+ Assert.IsNull (bindable.GetValue (ItemsView<BindableObject>.ItemTemplateProperty));
+
+ var collection = new List<string> { "foo", "bar", "baz" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ const int index = 0;
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.IsNotNull (content);
+
+ TextCell textCell = content as TextCell;
+ Assert.IsNotNull (textCell, "Content was did not match the template type, expected {0} but got {1}", typeof(TextCell), content.GetType());
+
+ Assert.AreSame (collection[index], textCell.BindingContext);
+ Assert.AreSame (collection[index], textCell.Text);
+
+ BindableObject content2 = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.AreSame (content, content2);
+ }
+
+ [Test]
+ public void GetOrCreateContentAfterTemplateChange()
+ {
+ var collection = new List<string> { "foo", "bar", "baz" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ const int index = 0;
+
+ DataTemplate template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, new Binding ("."));
+ bindable.SetValue (ItemsView<BindableObject>.ItemTemplateProperty, template);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.That (content, Is.InstanceOf<TextCell>());
+
+ template = new DataTemplate (typeof (SwitchCell));
+ template.SetBinding (SwitchCell.TextProperty, new Binding ("."));
+
+ bindable.SetValue (ItemsView<BindableObject>.ItemTemplateProperty, template);
+
+ BindableObject content2 = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.IsNotNull (content2);
+ Assert.That (content2, Is.InstanceOf<SwitchCell>());
+
+ var switchCell = (SwitchCell) content2;
+ Assert.AreSame (collection[index], switchCell.BindingContext);
+ }
+
+ [Test]
+ public void GetOrCreateContentAfterItemsSourceChanged()
+ {
+ var collection = new List<string> { "foo", "bar", "baz" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ const int index = 0;
+
+ DataTemplate template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, new Binding ("."));
+ bindable.SetValue (ItemsView<BindableObject>.ItemTemplateProperty, template);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+ Assert.IsNotNull (content);
+
+ collection = new List<string> { "we", "wee", "weee" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ var content2 = (TextCell)bindable.TemplatedItems.GetOrCreateContent (index, collection[index]);
+
+ Assert.AreNotSame (content, content2);
+ Assert.AreSame (collection[index], content2.BindingContext);
+ Assert.AreSame (collection[index], content2.Text);
+ }
+
+ /*[Test]
+ public void GetOrCreateContentAfterInfiniteScrollingChanged()
+ {
+ var collection = new List<string> { "foo", "bar", "baz" };
+ bindable.SetValue (ItemsView.ItemsSourceProperty, collection);
+
+ const int index = 0;
+
+ DataTemplate template = new DataTemplate (typeof (TextCell));
+ template.SetBinding (TextCell.TextProperty, new Binding ("."));
+ bindable.SetValue (ItemsView.ItemTemplateProperty, template);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (index, collection[index], o => new TextCell (o.ToString()));
+ Assert.IsNotNull (content);
+
+ bindable.SetValue (ItemsView.InfiniteScrollingProperty, true);
+
+ var content2 = (TextCell)bindable.TemplatedItems.GetOrCreateContent (index, collection[index], o => new TextCell (o.ToString()));
+
+ Assert.AreNotSame (content, content2);
+ Assert.AreSame (collection[index], content2.BindingContext);
+ Assert.AreSame (collection[index], content2.Text);
+ }*/
+
+ [Test]
+ [Description ("Make sure we're not duplicate cell instances for an equal item if it's a different index")]
+ public void GetOrCreateContentEqualItemDifferentItemDifferentIndex()
+ {
+ Assert.IsNull (bindable.GetValue (ItemsView<BindableObject>.ItemTemplateProperty));
+
+ var collection = new List<string> { "foo", "foo" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (0, collection[0]);
+ Assert.IsNotNull (content);
+
+ TextCell textCell = content as TextCell;
+ Assert.IsNotNull (textCell, "Content was did not match the template type, expected {0} but got {1}", typeof(TextCell), content.GetType());
+
+ Assert.AreSame (collection[0], textCell.BindingContext);
+ Assert.AreSame (collection[0], textCell.Text);
+
+ BindableObject content2 = bindable.TemplatedItems.GetOrCreateContent (1, collection[1]);
+ Assert.AreNotSame (content, content2);
+
+ Assert.AreSame (collection[1], textCell.BindingContext);
+ Assert.AreSame (collection[1], textCell.Text);
+ }
+
+ [Test]
+ [Description ("Make sure we're not duplicate cell instances for the same item if it's a different index")]
+ public void GetOrCreateContentEqualItemSameItemDifferentIndex()
+ {
+ Assert.IsNull (bindable.GetValue (ItemsView<BindableObject>.ItemTemplateProperty));
+
+ string item = "foo";
+
+ var collection = new List<string> { item, item };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ BindableObject content = bindable.TemplatedItems.GetOrCreateContent (0, item);
+ Assert.IsNotNull (content);
+
+ TextCell textCell = content as TextCell;
+ Assert.IsNotNull (textCell, "Content was did not match the template type, expected {0} but got {1}", typeof(TextCell), content.GetType());
+
+ Assert.AreSame (item, textCell.BindingContext);
+ Assert.AreSame (item, textCell.Text);
+
+ BindableObject content2 = bindable.TemplatedItems.GetOrCreateContent (1, item);
+ Assert.AreNotSame (content, content2);
+
+ Assert.AreSame (item, textCell.BindingContext);
+ Assert.AreSame (item, textCell.Text);
+ }
+
+ [Test]
+ public void ItemsSourceInsertPreRealzied()
+ {
+ var collection = new ObservableCollection<string> { "foo", "bar" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ collection.Insert (1, "baz");
+
+ Assert.That (bindable.TemplatedItems.Count, Is.EqualTo (3));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (0, collection[0]).BindingContext, Is.SameAs (collection[0]));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (1, collection[1]).BindingContext, Is.SameAs (collection[1]));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (2, collection[2]).BindingContext, Is.SameAs (collection[2]));
+ }
+
+ [Test]
+ public void ItemsSourceInsertPostRealized()
+ {
+ var collection = new ObservableCollection<string> { "foo", "bar" };
+ bindable.SetValue (ItemsView<BindableObject>.ItemsSourceProperty, collection);
+
+ // Force the handler to realize/create the content
+ bindable.TemplatedItems.GetOrCreateContent (0, collection[0]);
+ bindable.TemplatedItems.GetOrCreateContent (1, collection[1]);
+
+ collection.Insert (1, "baz");
+
+ Assert.That (bindable.TemplatedItems.Count, Is.EqualTo (3));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (0, collection[0]).BindingContext, Is.SameAs (collection[0]));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (1, collection[1]).BindingContext, Is.SameAs (collection[1]));
+ Assert.That (bindable.TemplatedItems.GetOrCreateContent (2, collection[2]).BindingContext, Is.SameAs (collection[2]));
+ }
+
+ [TestCase (0, 0, 0)]
+ [TestCase (3, 1, 0)]
+ public void GetGroupIndexFromGlobalGroupIndex (int globalIndex, int expectedIndex, int expectedLeftOver)
+ {
+ var collection = new[] {
+ new[] { "foo", "fad" },
+ new[] { "bar", "baz" }
+ };
+ bindable.ItemsSource = collection;
+ bindable.IsGroupingEnabled = true;
+
+ int leftOver;
+ int index = bindable.TemplatedItems.GetGroupIndexFromGlobal (globalIndex, out leftOver);
+ Assert.That (index, Is.EqualTo (expectedIndex));
+ Assert.That (leftOver, Is.EqualTo (expectedLeftOver));
+ }
+
+ [TestCase (1, 0, 1)]
+ [TestCase (2, 0, 2)]
+ [TestCase (4, 1, 1)]
+ [TestCase (5, 1, 2)]
+ public void GetGroupIndexFromGlobalItemIndex (int globalIndex, int expectedIndex, int expectedLeftOver)
+ {
+ var collection = new[] {
+ new[] { "foo", "fad" },
+ new[] { "bar", "baz" }
+ };
+ bindable.ItemsSource = collection;
+ bindable.IsGroupingEnabled = true;
+
+ int leftOver;
+ int index = bindable.TemplatedItems.GetGroupIndexFromGlobal (globalIndex, out leftOver);
+ Assert.That (index, Is.EqualTo (expectedIndex));
+ Assert.That (leftOver, Is.EqualTo (expectedLeftOver));
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItem ([Values (0, 1, 2)] int group, [Values (0, 1, 2)] int index)
+ {
+ var collection = new[] {
+ new[] { "foo", "fad" },
+ new[] { "bar", "baz" }
+ };
+ bindable.ItemsSource = collection;
+ bindable.IsGroupingEnabled = true;
+
+ object item = null;
+ if (group < collection.Length) {
+ if (index < collection[group].Length)
+ item = collection[group][index];
+ }
+
+ if (item == null) {
+ item = "not in here";
+ group = index = -1;
+ }
+
+ var location = bindable.TemplatedItems.GetGroupAndIndexOfItem (item);
+ Assert.That (location.Item1, Is.EqualTo (group), "Group index was incorrect");
+ Assert.That (location.Item2, Is.EqualTo (index), "Item index was incorrect");
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItemNotGrouped ()
+ {
+ var items = Enumerable.Range (0, 10).ToList ();
+ bindable.ItemsSource = items;
+
+ var location = bindable.TemplatedItems.GetGroupAndIndexOfItem (null, items[2]);
+
+ Assert.That (location.Item1, Is.EqualTo (0));
+ Assert.That (location.Item2, Is.EqualTo (2));
+ }
+
+ [Test]
+ public void ItemsSourcePropertyChangedWithBindable()
+ {
+ bool raised = false;
+ bindable.TemplatedItems.PropertyChanged += (s, e) => {
+ if (e.PropertyName == "ItemsSource")
+ raised = true;
+ };
+
+ bindable.ItemsSource = new object[0];
+
+ Assert.That (raised, Is.True, "INPC not raised for ItemsSource");
+ }
+
+ [Test]
+ public void IndexCorrectAfterMovingGroups()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.IsGroupingEnabled = true;
+
+ items.Move (0, 1);
+
+ var til = bindable.TemplatedItems.GetGroup (1);
+ int index = GetIndex (til.HeaderContent);
+
+ Assert.That (index, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void ShortNameSetBeforeGrouping()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupDisplayBinding = new Binding (".[0]");
+ bindable.GroupShortNameBinding = new Binding (".[0]");
+ bindable.IsGroupingEnabled = true;
+
+ Assert.That (bindable.TemplatedItems.ShortNames[0], Is.EqualTo ("foo"));
+ }
+
+ [Test]
+ public void ItemAddedWithShortNameSetButUngrouped()
+ {
+ var items = new ObservableCollection<string> { "foo", "bar" };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+
+ Assert.That (() => items.Add ("baz"), Throws.Nothing);
+ }
+
+ [Test]
+ public void ItemAddedWithShortNameSetButGroupingDisabled()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+ bindable.IsGroupingEnabled = false;
+
+ Assert.That (() => items.Add (new ObservableCollection<string>()), Throws.Nothing);
+ }
+
+ int GetIndex (BindableObject item)
+ {
+ return TemplatedItemsList<ItemsView<BindableObject>, BindableObject>.GetIndex (item);
+ }
+
+ [Test]
+ public void GetIndex()
+ {
+ var items = new List<string> { "foo", "bar", "baz" };
+
+ bindable.ItemsSource = items;
+
+ BindableObject item = bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+ int index = GetIndex (item);
+ Assert.That (index, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetIndexAfterInsert()
+ {
+ var items = new ObservableCollection<string> { "foo", "bar", "baz" };
+
+ bindable.ItemsSource = items;
+
+ BindableObject originalItem = bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ items.Insert (1, "fad");
+
+ BindableObject item = bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ int index = GetIndex (item);
+ Assert.That (index, Is.EqualTo (1));
+
+ index = GetIndex (originalItem);
+ Assert.That (index, Is.EqualTo (2));
+ }
+
+ [Test]
+ public void GetIndexAfterMove()
+ {
+ var items = new ObservableCollection<string> { "foo", "bar", "baz" };
+
+ bindable.ItemsSource = items;
+
+ BindableObject item0 = bindable.TemplatedItems.GetOrCreateContent (0, items[0]);
+ BindableObject item1 = bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+ BindableObject item2 = bindable.TemplatedItems.GetOrCreateContent (2, items[2]);
+
+ items.Move (0, 2); // foo, bar, baz becomes bar (1), baz (2), foo (0)
+
+ Assert.That (GetIndex (item0), Is.EqualTo (2));
+ Assert.That (GetIndex (item1), Is.EqualTo (0));
+ Assert.That (GetIndex (item2), Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetIndexAfterRemove()
+ {
+ var items = new ObservableCollection<string> { "foo", "bar", "baz" };
+
+ bindable.ItemsSource = items;
+
+ BindableObject item1 = bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+ BindableObject item2 = bindable.TemplatedItems.GetOrCreateContent (2, items[2]);
+
+ items.RemoveAt (0);
+
+ Assert.That (GetIndex (item1), Is.EqualTo (0));
+ Assert.That (GetIndex (item2), Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetGroup()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var til = bindable.TemplatedItems.GetGroup (1);
+ var item = til[1];
+
+ var group = TemplatedItemsList<ItemsView<BindableObject>, BindableObject>.GetGroup (item);
+
+ Assert.That (group, Is.SameAs (til));
+ }
+
+ [Test]
+ public void GetIndexGrouped()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var til = bindable.TemplatedItems.GetGroup (1);
+ var item = til[1];
+
+ int index = GetIndex (item);
+ Assert.That (index, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItem()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var result = bindable.TemplatedItems.GetGroupAndIndexOfItem (items[1], items[1][1]);
+
+ Assert.That (result.Item1, Is.EqualTo (1));
+ Assert.That (result.Item2, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItemNoGroup()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var result = bindable.TemplatedItems.GetGroupAndIndexOfItem (null, items[1][1]);
+
+ Assert.That (result.Item1, Is.EqualTo (1));
+ Assert.That (result.Item2, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItemNotFound()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var group = new ObservableCollection<string> { "bam" };
+
+ var result = bindable.TemplatedItems.GetGroupAndIndexOfItem (group, group[0]);
+
+ Assert.That (result.Item1, Is.EqualTo (-1));
+ Assert.That (result.Item2, Is.EqualTo (-1));
+ }
+
+ [Test]
+ public void GetGroupAndIndexOfItemItemNotFound()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var result = bindable.TemplatedItems.GetGroupAndIndexOfItem (items[1], "bam");
+
+ Assert.That (result.Item1, Is.EqualTo (1));
+ Assert.That (result.Item2, Is.EqualTo (-1));
+ }
+
+ [Test]
+ [Description ("Issue #2464: ANE thrown when moving items in a ListView")]
+ public void MovingPastRealizedWindowAndBackDoesntThrow()
+ {
+ var items = new ObservableCollection<string> (Enumerable.Range (0, 100).Select (i => i.ToString()));
+
+ bindable.ItemsSource = items;
+
+ bindable.TemplatedItems.GetOrCreateContent (0, items[0]);
+ bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ items.Move (0, 3);
+ Assert.That (() => items.Move (3, 2), Throws.Nothing);
+
+ Assert.That (GetIndex (bindable.TemplatedItems[0]), Is.EqualTo (0));
+ Assert.That (GetIndex (bindable.TemplatedItems[1]), Is.EqualTo (1));
+ Assert.That (GetIndex (bindable.TemplatedItems[2]), Is.EqualTo (2));
+ Assert.That (GetIndex (bindable.TemplatedItems[3]), Is.EqualTo (3));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfItem ()
+ {
+ var items = new ObservableCollection<string> (Enumerable.Range (0, 100).Select (i => i.ToString()));
+ bindable.ItemsSource = items;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem ("50");
+ Assert.That (global, Is.EqualTo (50));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfItemNotFound ()
+ {
+ var items = new ObservableCollection<string> (Enumerable.Range (0, 100).Select (i => i.ToString()));
+ bindable.ItemsSource = items;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem ("101");
+ Assert.That (global, Is.EqualTo (-1));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfItemGrouped ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem ("baz");
+ Assert.That (global, Is.EqualTo (5));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfItemGroupedNotFound ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem ("101");
+ Assert.That (global, Is.EqualTo (-1));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfGroupItemGrouped ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "baz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem (items[1], "baz");
+ Assert.That (global, Is.EqualTo (5));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfGroupItemGroupedNotFound ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "foo", "faz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem (items[1], "bar");
+ Assert.That (global, Is.EqualTo (-1));
+ }
+
+ [Test]
+ public void GetGlobalIndexOfGroupItemGroupedGroupNotFound ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "foo", "faz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ int global = bindable.TemplatedItems.GetGlobalIndexOfItem (new object(), "foo");
+ Assert.That (global, Is.EqualTo (-1));
+ }
+
+ [Test]
+ public void SetupContentOnCreation()
+ {
+ var items = new ObservableCollection<string> {
+ "Foo",
+ "Bar"
+ };
+
+ bindable.ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding (".") }
+ }
+ };
+
+ int count = 0;
+ bindable.Hooked += obj => {
+ count++;
+ Assert.That (obj, Is.InstanceOf (typeof (TextCell)));
+ Assert.That (items, Contains.Item (obj.BindingContext));
+ };
+
+ bindable.ItemsSource = items;
+
+ bindable.TemplatedItems.GetOrCreateContent (0, items[0]);
+ bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ Assert.That (count, Is.EqualTo (2));
+ }
+
+ [Test]
+ public void UnhookGroupOnRemoval()
+ {
+ var inner = new ObservableCollection<string> {
+ "Foo",
+ };
+
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ inner
+ };
+
+ bindable.IsGroupingEnabled = true;
+ bindable.GroupDisplayBinding = new Binding (".[0]");
+
+ bindable.ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding (".") }
+ }
+ };
+
+ int count = 0;
+ bindable.Unhooked += obj => {
+ if (count == 0) {
+ Assert.That (obj.BindingContext, Is.InstanceOf (typeof (TemplatedItemsList<ItemsView<BindableObject>, BindableObject>)));
+ Assert.That (((TemplatedItemsList<ItemsView<BindableObject>, BindableObject>) obj.BindingContext).ListProxy.ProxiedEnumerable, Is.SameAs (inner));
+ } else {
+ Assert.That (obj.BindingContext, Is.SameAs (inner[0]));
+ }
+
+ count++;
+ };
+
+ bindable.ItemsSource = items;
+
+ var til = bindable.TemplatedItems.GetGroup (0);
+ til.GetOrCreateContent (0, inner[0]);
+
+ Assume.That (til, Is.Not.Null);
+ Assume.That (til.HeaderContent, Is.Not.Null);
+ Assume.That (count, Is.EqualTo (0));
+
+ items.RemoveAt (0);
+
+ Assert.That (count, Is.EqualTo (2));
+ }
+
+ [Test]
+ public void HookAndUnhookGroupOnReplace()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> {
+ "Foo",
+ }
+ };
+
+ bindable.IsGroupingEnabled = true;
+ bindable.GroupDisplayBinding = new Binding (".[0]");
+ bindable.ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding (".") }
+ }
+ };
+
+ bindable.ItemsSource = items;
+
+ var til = bindable.TemplatedItems.GetGroup (0);
+ til.GetOrCreateContent (0, items[0][0]);
+
+ Assume.That (til, Is.Not.Null);
+ Assume.That (til.HeaderContent, Is.Not.Null);
+
+ int hcount = 0;
+ bindable.Hooked += obj => {
+ Assert.That (obj.BindingContext, Is.InstanceOf (typeof (TemplatedItemsList<ItemsView<BindableObject>, BindableObject>)));
+ hcount++;
+ };
+
+ int ucount = 0;
+ bindable.Unhooked += obj => {
+ Assert.That (obj.BindingContext,
+ Is.InstanceOf (typeof (TemplatedItemsList<ItemsView<BindableObject>, BindableObject>))
+ .Or.EqualTo ("Foo"));
+
+ ucount++;
+ };
+
+ items[0] = new ObservableCollection<string> { "Baz" };
+
+ Assert.That (hcount, Is.EqualTo (1));
+ Assert.That (ucount, Is.EqualTo (2));
+ }
+
+ [Test]
+ public void UnhookContentOnRemoval()
+ {
+ var items = new ObservableCollection<string> {
+ "Foo",
+ "Bar"
+ };
+
+ bindable.ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding (".") }
+ }
+ };
+
+ int count = 0;
+ bindable.Unhooked += obj => {
+ count++;
+ Assert.That (obj, Is.InstanceOf (typeof (TextCell)));
+ Assert.That (obj.BindingContext, Is.EqualTo ("Foo"));
+ };
+
+ bindable.ItemsSource = items;
+
+ bindable.TemplatedItems.GetOrCreateContent (0, items[0]);
+ bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ Assume.That (count, Is.EqualTo (0));
+
+ items.RemoveAt (0);
+
+ Assert.That (count, Is.EqualTo (1));
+ }
+
+ [Test]
+ public void HookAndUnhookContentOnReplace()
+ {
+ var items = new ObservableCollection<string> {
+ "Foo",
+ "Bar"
+ };
+
+ bindable.ItemTemplate = new DataTemplate (typeof (TextCell)) {
+ Bindings = {
+ { TextCell.TextProperty, new Binding (".") }
+ }
+ };
+
+ bindable.ItemsSource = items;
+
+ bindable.TemplatedItems.GetOrCreateContent (0, items[0]);
+ bindable.TemplatedItems.GetOrCreateContent (1, items[1]);
+
+ int hcount = 0;
+ bindable.Hooked += obj => {
+ hcount++;
+ Assert.That (obj, Is.InstanceOf (typeof (TextCell)));
+ Assert.That (obj.BindingContext, Is.EqualTo ("Baz"));
+ };
+
+ int ucount = 0;
+ bindable.Unhooked += obj => {
+ ucount++;
+ Assert.That (obj, Is.InstanceOf (typeof (TextCell)));
+ Assert.That (obj.BindingContext, Is.EqualTo ("Foo"));
+ };
+
+ items[0] = "Baz";
+
+ Assert.That (hcount, Is.EqualTo (1));
+ Assert.That (ucount, Is.EqualTo (1));
+ }
+
+ [Test (Description = "If the cell exists and has an index, we still need to check if it's in the group asked for")]
+ public void IndexOfFailsForCellInAnotherGroup ()
+ {
+ var items = new ObservableCollection<ObservableCollection<string>> {
+ new ObservableCollection<string> { "foo", "faz" },
+ new ObservableCollection<string> { "bar", "baz" }
+ };
+
+ bindable.ItemsSource = items;
+ bindable.GroupShortNameBinding = new Binding (".");
+ bindable.IsGroupingEnabled = true;
+
+ var group1 = bindable.TemplatedItems.GetGroup (0);
+ var cell = group1[1];
+
+ Assume.That (group1.IndexOf (cell), Is.EqualTo (1));
+
+ var group2 = bindable.TemplatedItems.GetGroup (1);
+
+ Assert.That (group2.IndexOf (cell), Is.EqualTo (-1));
+ }
+ }
+}