From 9856711494f14cbf7d59cbd3f9ddc1dda7112cfc Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 8 Mar 2023 15:27:04 +0100 Subject: [PATCH] Don't modify logical tree in ItemsSource mode. --- src/Avalonia.Controls/ItemsControl.cs | 17 +++++----- .../ItemsControlTests.cs | 31 +++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index b476df5fda..ee2899e50c 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -573,15 +573,18 @@ namespace Avalonia.Controls /// The event args. private protected virtual void OnItemsViewCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { - switch (e.Action) + if (!_items.IsReadOnly) { - case NotifyCollectionChangedAction.Add: - AddControlItemsToLogicalChildren(e.NewItems); - break; + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + AddControlItemsToLogicalChildren(e.NewItems); + break; - case NotifyCollectionChangedAction.Remove: - RemoveControlItemsFromLogicalChildren(e.OldItems); - break; + case NotifyCollectionChangedAction.Remove: + RemoveControlItemsFromLogicalChildren(e.OldItems); + break; + } } ItemCount = ItemsView.Count; diff --git a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs index 9b28ca11f0..12fc0a82ed 100644 --- a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs @@ -249,6 +249,37 @@ namespace Avalonia.Controls.UnitTests Assert.Null(((ILogical)child).LogicalParent); } + [Fact] + public void Assigning_ItemsSource_Should_Not_Fire_LogicalChildren_CollectionChanged_Before_ApplyTemplate() + { + var target = new ItemsControl(); + var child = new Control(); + var called = false; + + ((ILogical)target).LogicalChildren.CollectionChanged += (s, e) => called = true; + + var list = new AvaloniaList(new[] { child }); + target.ItemsSource = list; + + Assert.False(called); + } + + [Fact] + public void Changing_ItemsSource_Should_Not_Fire_LogicalChildren_CollectionChanged_Before_ApplyTemplate() + { + var target = new ItemsControl(); + var child = new Control(); + var called = false; + + ((ILogical)target).LogicalChildren.CollectionChanged += (s, e) => called = true; + + var list = new AvaloniaList(); + target.ItemsSource = list; + list.Add(child); + + Assert.False(called); + } + [Fact] public void Clearing_Items_Should_Clear_Child_Controls_Parent() {