From 0617aa23a5e7253db016ebe5849f7917ce1b68aa Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 17 Oct 2015 18:05:09 +0200 Subject: [PATCH] Support Replace and Reset in ItemsPresenter. --- .../Presenters/ItemsPresenter.cs | 28 ++++++++++++-- .../Presenters/ItemsPresenterTests.cs | 37 +++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/Perspex.Controls/Presenters/ItemsPresenter.cs b/src/Perspex.Controls/Presenters/ItemsPresenter.cs index 12327bdb48..0a80376aa7 100644 --- a/src/Perspex.Controls/Presenters/ItemsPresenter.cs +++ b/src/Perspex.Controls/Presenters/ItemsPresenter.cs @@ -3,6 +3,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Collections.Specialized; using Perspex.Controls.Generators; using Perspex.Controls.Templates; @@ -237,18 +238,37 @@ namespace Perspex.Controls.Presenters if (_createdPanel) { var generator = ItemContainerGenerator; + IEnumerable containers; // TODO: Handle Move and Replace etc. switch (e.Action) { case NotifyCollectionChangedAction.Add: - Panel.Children.AddRange( - generator.Materialize(e.NewStartingIndex, e.NewItems, MemberSelector)); + containers = generator.Materialize(e.NewStartingIndex, e.NewItems, MemberSelector); + Panel.Children.AddRange(containers); break; case NotifyCollectionChangedAction.Remove: - Panel.Children.RemoveAll( - generator.RemoveRange(e.OldStartingIndex, e.OldItems.Count)); + containers = generator.RemoveRange(e.OldStartingIndex, e.OldItems.Count); + Panel.Children.RemoveAll(containers); + break; + + case NotifyCollectionChangedAction.Replace: + generator.Dematerialize(e.OldStartingIndex, e.OldItems.Count); + containers = generator.Materialize(e.NewStartingIndex, e.NewItems, MemberSelector); + + var i = e.NewStartingIndex; + + foreach (var container in containers) + { + Panel.Children[i++] = container; + } + + break; + + case NotifyCollectionChangedAction.Reset: + Panel.Children.RemoveAll(generator.Clear()); + Panel.Children.AddRange(generator.Materialize(0, Items, MemberSelector)); break; } diff --git a/tests/Perspex.Controls.UnitTests/Presenters/ItemsPresenterTests.cs b/tests/Perspex.Controls.UnitTests/Presenters/ItemsPresenterTests.cs index a41d4e326d..c6354cc417 100644 --- a/tests/Perspex.Controls.UnitTests/Presenters/ItemsPresenterTests.cs +++ b/tests/Perspex.Controls.UnitTests/Presenters/ItemsPresenterTests.cs @@ -1,6 +1,7 @@ // Copyright (c) The Perspex Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. +using System.Collections.ObjectModel; using System.Linq; using Perspex.Collections; using Perspex.Controls.Generators; @@ -80,6 +81,42 @@ namespace Perspex.Controls.UnitTests.Presenters [Fact] public void Clearing_Items_Should_Remove_Containers() + { + var items = new ObservableCollection { "foo", "bar" }; + var target = new ItemsPresenter + { + Items = items, + }; + + target.ApplyTemplate(); + items.Clear(); + + Assert.Empty(target.Panel.Children); + Assert.Empty(target.ItemContainerGenerator.Containers); + } + + [Fact] + public void Replacing_Items_Should_Update_Containers() + { + var items = new ObservableCollection { "foo", "bar", "baz" }; + var target = new ItemsPresenter + { + Items = items, + }; + + target.ApplyTemplate(); + items[1] = "baz"; + + var text = target.Panel.Children + .OfType() + .Select(x => x.Text) + .ToList(); + + Assert.Equal(new[] { "foo", "baz", "baz" }, text); + } + + [Fact] + public void Setting_Items_To_Null_Should_Remove_Containers() { var target = new ItemsPresenter {