From e53cbd13f95ccb7e41c9f08676c770e0cabba002 Mon Sep 17 00:00:00 2001 From: danwalmsley Date: Tue, 8 Nov 2016 16:49:10 +0000 Subject: [PATCH 01/32] Added failing unit test for Carousel --- tests/Avalonia.Controls.UnitTests/CarouselTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/CarouselTests.cs b/tests/Avalonia.Controls.UnitTests/CarouselTests.cs index 0e3c6f5953..e91ab02327 100644 --- a/tests/Avalonia.Controls.UnitTests/CarouselTests.cs +++ b/tests/Avalonia.Controls.UnitTests/CarouselTests.cs @@ -50,8 +50,9 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(1, target.GetLogicalChildren().Count()); var child = target.GetLogicalChildren().Single(); - Assert.IsType(child); - Assert.Equal("Foo", ((ContentPresenter)child).Content); + + Assert.IsType(child); + Assert.Equal("Foo", ((TextBlock)child).Text); } [Fact] From 759a8a845de93c15d973f799f3840344f3306de3 Mon Sep 17 00:00:00 2001 From: danwalmsley Date: Fri, 11 Nov 2016 16:48:29 +0000 Subject: [PATCH 02/32] initial attempt to set logical children correctly. --- src/Avalonia.Controls/ItemsControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 8f92cc43b7..9253a5801b 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -234,7 +234,7 @@ namespace Avalonia.Controls // it was added to the Items collection. if (container.ContainerControl != null && container.ContainerControl != container.Item) { - toAdd.Add(container.ContainerControl); + toAdd.Add((container.ContainerControl as ContentPresenter).Content as ILogical); } } From 2c3c73edac0d83bf1d9fd12ff2a9c6a906be6ea1 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Nov 2016 20:13:41 +0000 Subject: [PATCH 03/32] Items control adds the content presenters child as its logical child. --- src/Avalonia.Controls/ItemsControl.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 9253a5801b..922f9f0df6 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -234,7 +234,8 @@ namespace Avalonia.Controls // it was added to the Items collection. if (container.ContainerControl != null && container.ContainerControl != container.Item) { - toAdd.Add((container.ContainerControl as ContentPresenter).Content as ILogical); + (container.ContainerControl as ContentPresenter).UpdateChild(); + toAdd.Add((container.ContainerControl as ContentPresenter).Child as ILogical); } } From c5c09275b5f054d8426710a05d2c015e47f466be Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Nov 2016 20:24:45 +0000 Subject: [PATCH 04/32] Items control removes the logical child correctly. --- src/Avalonia.Controls/ItemsControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 922f9f0df6..1c6afa4279 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -257,7 +257,7 @@ namespace Avalonia.Controls // when it is removed from the Items collection. if (container?.ContainerControl != container?.Item) { - toRemove.Add(container.ContainerControl); + toRemove.Add((container.ContainerControl as ContentPresenter).Child); } } From a5a59c3e8c35c7ae1ede730540f4a7e48e109516 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Nov 2016 20:25:11 +0000 Subject: [PATCH 05/32] Updated ItemsControl test for new behaviour. --- tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs index dcbc71b9a1..37646f48c0 100644 --- a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs @@ -138,7 +138,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Adding_String_Item_Should_Make_ContentPresenter_Appear_In_LogicalChildren() + public void Adding_String_Item_Should_Make_TextBlock_Appear_In_LogicalChildren() { var target = new ItemsControl(); var child = new Control(); From ce224fd7436ce7d60528573ef2649c36a28f90be Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Nov 2016 20:52:43 +0000 Subject: [PATCH 06/32] Add ContainerType property to IItemContainerGenerator --- src/Avalonia.Controls/Generators/IItemContainerGenerator.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs index ba584e33b9..d139c95fd4 100644 --- a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs +++ b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs @@ -22,6 +22,11 @@ namespace Avalonia.Controls.Generators /// IDataTemplate ItemTemplate { get; set; } + /// + /// Gets the ContainerType, or null if its an untyped ContainerGenerator. + /// + Type ContainerType { get; } + /// /// Signalled whenever new containers are materialized. /// From 21f97ac10851c7c1319b11682519e451e3ae6174 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Nov 2016 21:01:19 +0000 Subject: [PATCH 07/32] Add implementation of ContainerType property --- .../Generators/ItemContainerGenerator.cs | 8 ++++++++ .../Generators/ItemContainerGenerator`1.cs | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs index 4d65210002..fbd71122aa 100644 --- a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs +++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs @@ -50,6 +50,14 @@ namespace Avalonia.Controls.Generators /// public IControl Owner { get; } + public virtual Type ContainerType + { + get + { + return null; + } + } + /// public ItemContainerInfo Materialize( int index, diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs index 3aa2181cd4..1cc7b537ac 100644 --- a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs +++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs @@ -34,6 +34,15 @@ namespace Avalonia.Controls.Generators ContentTemplateProperty = contentTemplateProperty; } + /// + public override Type ContainerType + { + get + { + return typeof(T); + } + } + /// /// Gets the container's Content property. /// From ba89e646c4c7b3e0143b1353a562889876515d37 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Nov 2016 21:01:51 +0000 Subject: [PATCH 08/32] ItemsControl uses the ContainerType property to check if its a typed container. --- src/Avalonia.Controls/ItemsControl.cs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 1c6afa4279..c3c78e9e88 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -14,6 +14,8 @@ using Avalonia.Controls.Templates; using Avalonia.Controls.Utils; using Avalonia.LogicalTree; using Avalonia.Metadata; +using System; + namespace Avalonia.Controls { @@ -219,6 +221,7 @@ namespace Avalonia.Controls return new ItemContainerGenerator(this); } + /// /// Called when new containers are materialized for the by its /// . @@ -229,13 +232,20 @@ namespace Avalonia.Controls var toAdd = new List(); foreach (var container in e.Containers) - { + { // If the item is its own container, then it will be added to the logical tree when // it was added to the Items collection. if (container.ContainerControl != null && container.ContainerControl != container.Item) { - (container.ContainerControl as ContentPresenter).UpdateChild(); - toAdd.Add((container.ContainerControl as ContentPresenter).Child as ILogical); + if (ItemContainerGenerator.ContainerType == null) + { + (container.ContainerControl as ContentPresenter).UpdateChild(); + toAdd.Add((container.ContainerControl as ContentPresenter).Child as ILogical); + } + else + { + toAdd.Add(container.ContainerControl); + } } } @@ -257,7 +267,14 @@ namespace Avalonia.Controls // when it is removed from the Items collection. if (container?.ContainerControl != container?.Item) { - toRemove.Add((container.ContainerControl as ContentPresenter).Child); + if (ItemContainerGenerator.ContainerType == null) + { + toRemove.Add((container.ContainerControl as ContentPresenter).Child); + } + else + { + toRemove.Add(container.ContainerControl); + } } } From f3d2520f6c17a684ddfb683315a4003ef47f6878 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Nov 2016 21:02:16 +0000 Subject: [PATCH 09/32] Fix ItemsControl tests. --- tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs index 37646f48c0..fafc1a5ab6 100644 --- a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs @@ -150,7 +150,7 @@ namespace Avalonia.Controls.UnitTests var logical = (ILogical)target; Assert.Equal(1, logical.LogicalChildren.Count); - Assert.IsType(logical.LogicalChildren[0]); + Assert.IsType(logical.LogicalChildren[0]); } [Fact] From 261b63dd4c8645b3ec14cfc1d903e47e89d48807 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Nov 2016 13:29:21 +0000 Subject: [PATCH 10/32] fix whitespace --- src/Avalonia.Controls/ItemsControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index c3c78e9e88..89bd1136db 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -232,7 +232,7 @@ namespace Avalonia.Controls var toAdd = new List(); foreach (var container in e.Containers) - { + { // If the item is its own container, then it will be added to the logical tree when // it was added to the Items collection. if (container.ContainerControl != null && container.ContainerControl != container.Item) From 4a17d2d32f233b25e80f5b3b50f583c3341e2276 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Nov 2016 13:31:35 +0000 Subject: [PATCH 11/32] ContainerType property implementations using improved syntax. --- .../Generators/ItemContainerGenerator.cs | 8 +------- .../Generators/ItemContainerGenerator`1.cs | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs index fbd71122aa..493a3f28f1 100644 --- a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs +++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs @@ -50,13 +50,7 @@ namespace Avalonia.Controls.Generators /// public IControl Owner { get; } - public virtual Type ContainerType - { - get - { - return null; - } - } + public virtual Type ContainerType => null; /// public ItemContainerInfo Materialize( diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs index 1cc7b537ac..259c524d59 100644 --- a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs +++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs @@ -35,13 +35,7 @@ namespace Avalonia.Controls.Generators } /// - public override Type ContainerType - { - get - { - return typeof(T); - } - } + public override Type ContainerType => typeof(T); /// /// Gets the container's Content property. From cf13ae34250c28365f2c019c86da7991cbf8c1e1 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Nov 2016 13:36:08 +0000 Subject: [PATCH 12/32] removed excessive casting. --- src/Avalonia.Controls/ItemsControl.cs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 89bd1136db..dc8f4db1b9 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -239,8 +239,17 @@ namespace Avalonia.Controls { if (ItemContainerGenerator.ContainerType == null) { - (container.ContainerControl as ContentPresenter).UpdateChild(); - toAdd.Add((container.ContainerControl as ContentPresenter).Child as ILogical); + var containerControl = container.ContainerControl as ContentPresenter; + + if(containerControl != null && containerControl is ILogical) + { + containerControl.UpdateChild(); + toAdd.Add(containerControl.Child as ILogical); + } + else + { + // TODO ? Throw exception or something else? + } } else { @@ -269,7 +278,16 @@ namespace Avalonia.Controls { if (ItemContainerGenerator.ContainerType == null) { - toRemove.Add((container.ContainerControl as ContentPresenter).Child); + var containerControl = container.ContainerControl as ContentPresenter; + + if(containerControl != null && containerControl.Child is ILogical) + { + toRemove.Add(containerControl.Child as ILogical); + } + else + { + // TODO throw exception ?? + } } else { From 5a43816db5068124e2bd4730a6eb588ae6586313 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Nov 2016 13:37:16 +0000 Subject: [PATCH 13/32] whitespace --- src/Avalonia.Controls/ItemsControl.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index dc8f4db1b9..581b8d8052 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -241,7 +241,7 @@ namespace Avalonia.Controls { var containerControl = container.ContainerControl as ContentPresenter; - if(containerControl != null && containerControl is ILogical) + if (containerControl != null && containerControl is ILogical) { containerControl.UpdateChild(); toAdd.Add(containerControl.Child as ILogical); @@ -280,14 +280,14 @@ namespace Avalonia.Controls { var containerControl = container.ContainerControl as ContentPresenter; - if(containerControl != null && containerControl.Child is ILogical) + if (containerControl != null && containerControl.Child is ILogical) { toRemove.Add(containerControl.Child as ILogical); - } + } else { // TODO throw exception ?? - } + } } else { From 59d499fee42151610911201e8355d68a6d4e3d72 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Nov 2016 17:45:02 +0000 Subject: [PATCH 14/32] ItemsControl ensure Containers Templated parent is null. --- src/Avalonia.Controls/ItemsControl.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 581b8d8052..9442eb908e 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -229,8 +229,6 @@ namespace Avalonia.Controls /// The details of the containers. protected virtual void OnContainersMaterialized(ItemContainerEventArgs e) { - var toAdd = new List(); - foreach (var container in e.Containers) { // If the item is its own container, then it will be added to the logical tree when @@ -244,7 +242,8 @@ namespace Avalonia.Controls if (containerControl != null && containerControl is ILogical) { containerControl.UpdateChild(); - toAdd.Add(containerControl.Child as ILogical); + LogicalChildren.Add(containerControl.Child as ILogical); + containerControl.SetValue(TemplatedParentProperty, null); } else { @@ -253,12 +252,10 @@ namespace Avalonia.Controls } else { - toAdd.Add(container.ContainerControl); + LogicalChildren.Add(container.ContainerControl); } } } - - LogicalChildren.AddRange(toAdd); } /// From 3af1cff1cae7a02e69710615928f718c747186bb Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Nov 2016 18:26:57 +0000 Subject: [PATCH 15/32] Fix ItemsControl preventing DataTemplates getting applied. --- src/Avalonia.Controls/ItemsControl.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 9442eb908e..44673ed0a7 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -241,6 +241,7 @@ namespace Avalonia.Controls if (containerControl != null && containerControl is ILogical) { + ((ISetLogicalParent)containerControl).SetParent(this); containerControl.UpdateChild(); LogicalChildren.Add(containerControl.Child as ILogical); containerControl.SetValue(TemplatedParentProperty, null); From 03afec55963ef731a24d235e2eb42da33f932125 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Nov 2016 19:15:58 +0000 Subject: [PATCH 16/32] fix bug checking wrong property for is ILogical --- src/Avalonia.Controls/ItemsControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 44673ed0a7..decc44883b 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -239,7 +239,7 @@ namespace Avalonia.Controls { var containerControl = container.ContainerControl as ContentPresenter; - if (containerControl != null && containerControl is ILogical) + if (containerControl != null && containerControl.Child is ILogical) { ((ISetLogicalParent)containerControl).SetParent(this); containerControl.UpdateChild(); From 59fd92dcfb8ba7bb1f38a2b6563110db863e5f96 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Nov 2016 19:32:15 +0000 Subject: [PATCH 17/32] Null check in ItemsControl on Materialized and Dematerialized, to prevent exceptions being thrown, trying to do is check on null. --- src/Avalonia.Controls/ItemsControl.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index decc44883b..1ddec7ac85 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -239,7 +239,7 @@ namespace Avalonia.Controls { var containerControl = container.ContainerControl as ContentPresenter; - if (containerControl != null && containerControl.Child is ILogical) + if (containerControl != null && containerControl.Child != null && containerControl.Child is ILogical) { ((ISetLogicalParent)containerControl).SetParent(this); containerControl.UpdateChild(); @@ -278,7 +278,7 @@ namespace Avalonia.Controls { var containerControl = container.ContainerControl as ContentPresenter; - if (containerControl != null && containerControl.Child is ILogical) + if (containerControl != null && containerControl.Child != null && containerControl.Child is ILogical) { toRemove.Add(containerControl.Child as ILogical); } From dac0da2caca437fff28ed64976f9ff53383ba7b4 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Nov 2016 19:49:18 +0000 Subject: [PATCH 18/32] Corrected logic for materialize methods. --- src/Avalonia.Controls/ItemsControl.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 1ddec7ac85..5b135a144d 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -239,11 +239,16 @@ namespace Avalonia.Controls { var containerControl = container.ContainerControl as ContentPresenter; - if (containerControl != null && containerControl.Child != null && containerControl.Child is ILogical) + if (containerControl != null) { ((ISetLogicalParent)containerControl).SetParent(this); containerControl.UpdateChild(); - LogicalChildren.Add(containerControl.Child as ILogical); + + if (containerControl.Child != null && containerControl.Child is ILogical) + { + LogicalChildren.Add(containerControl.Child as ILogical); + } + containerControl.SetValue(TemplatedParentProperty, null); } else From d398766c57e522db51f31651c714a9696f3fe54a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Nov 2016 19:55:44 +0000 Subject: [PATCH 19/32] remove excessive null check, is also serves for null check. --- src/Avalonia.Controls/ItemsControl.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 5b135a144d..b8621fc30b 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -244,7 +244,7 @@ namespace Avalonia.Controls ((ISetLogicalParent)containerControl).SetParent(this); containerControl.UpdateChild(); - if (containerControl.Child != null && containerControl.Child is ILogical) + if (containerControl.Child is ILogical) { LogicalChildren.Add(containerControl.Child as ILogical); } @@ -283,7 +283,7 @@ namespace Avalonia.Controls { var containerControl = container.ContainerControl as ContentPresenter; - if (containerControl != null && containerControl.Child != null && containerControl.Child is ILogical) + if (containerControl != null && containerControl.Child is ILogical) { toRemove.Add(containerControl.Child as ILogical); } From bcc6cc196ca1b0d862ff70365406974acbcdd740 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Nov 2016 22:17:00 +0000 Subject: [PATCH 20/32] Set TemplatedParentProperty null before calling update child so it doesnt end up seting the ItemsControls parent as the container.childs parent. Preventing it being removed from logical tree. --- src/Avalonia.Controls/ItemsControl.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index b8621fc30b..bf357edfd8 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -242,14 +242,14 @@ namespace Avalonia.Controls if (containerControl != null) { ((ISetLogicalParent)containerControl).SetParent(this); + containerControl.SetValue(TemplatedParentProperty, null); + containerControl.UpdateChild(); if (containerControl.Child is ILogical) { LogicalChildren.Add(containerControl.Child as ILogical); } - - containerControl.SetValue(TemplatedParentProperty, null); } else { @@ -286,6 +286,7 @@ namespace Avalonia.Controls if (containerControl != null && containerControl.Child is ILogical) { toRemove.Add(containerControl.Child as ILogical); + ((ISetLogicalParent)containerControl).SetParent(null); } else { From 8a3acecf2580faa164adc0565b8ef678b6ed34e8 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sun, 13 Nov 2016 13:01:22 +0000 Subject: [PATCH 21/32] Removed comments --- src/Avalonia.Controls/ItemsControl.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index bf357edfd8..2dac97726f 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -251,10 +251,6 @@ namespace Avalonia.Controls LogicalChildren.Add(containerControl.Child as ILogical); } } - else - { - // TODO ? Throw exception or something else? - } } else { @@ -288,10 +284,6 @@ namespace Avalonia.Controls toRemove.Add(containerControl.Child as ILogical); ((ISetLogicalParent)containerControl).SetParent(null); } - else - { - // TODO throw exception ?? - } } else { From 9a0fead20312419b814850ba7f737847e790a3e4 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sun, 13 Nov 2016 13:02:34 +0000 Subject: [PATCH 22/32] Added unit test to assert new behavior. --- .../ItemsControlTests.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs index fafc1a5ab6..e1c419080d 100644 --- a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs @@ -9,6 +9,8 @@ using Avalonia.Controls.Templates; using Avalonia.LogicalTree; using Avalonia.VisualTree; using Xunit; +using System.Collections.ObjectModel; +using Avalonia.UnitTests; namespace Avalonia.Controls.UnitTests { @@ -61,6 +63,32 @@ namespace Avalonia.Controls.UnitTests Assert.Null(container.TemplatedParent); } + [Fact] + public void Container_Child_Should_Have_LogicalParent_Set_To_Container() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var root = new Window(); + var target = new ItemsControl(); + + root.Content = target; + + var templatedParent = new Button(); + target.TemplatedParent = templatedParent; + target.Template = GetTemplate(); + + target.Items = new[] { "Foo" }; + + root.ApplyTemplate(); + target.ApplyTemplate(); + target.Presenter.ApplyTemplate(); + + var container = (ContentPresenter)target.Presenter.Panel.Children[0]; + + Assert.Equal(container.Child.Parent, container); + } + } + [Fact] public void Control_Item_Should_Be_Logical_Child_Before_ApplyTemplate() { @@ -170,6 +198,7 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new ILogical[0], target.GetLogicalChildren()); } + [Fact] public void Setting_Items_Should_Fire_LogicalChildren_CollectionChanged() From d3f4dacdbc72f596611da997ade3bd54422e7883 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sun, 13 Nov 2016 13:54:09 +0000 Subject: [PATCH 23/32] whitespace --- tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs index e1c419080d..b6a0ca2436 100644 --- a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs @@ -76,7 +76,7 @@ namespace Avalonia.Controls.UnitTests var templatedParent = new Button(); target.TemplatedParent = templatedParent; target.Template = GetTemplate(); - + target.Items = new[] { "Foo" }; root.ApplyTemplate(); @@ -198,7 +198,7 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new ILogical[0], target.GetLogicalChildren()); } - + [Fact] public void Setting_Items_Should_Fire_LogicalChildren_CollectionChanged() From 5b541165076ca6cab27694887ac3fffee4e7582d Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Nov 2016 22:27:42 +0000 Subject: [PATCH 24/32] Add missing inheritdoc comment. --- src/Avalonia.Controls/Generators/ItemContainerGenerator.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs index 493a3f28f1..882d2f4ddd 100644 --- a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs +++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs @@ -50,6 +50,7 @@ namespace Avalonia.Controls.Generators /// public IControl Owner { get; } + /// public virtual Type ContainerType => null; /// From 28ddbb21591d84d00b77bc475113e50278a706b1 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Nov 2016 22:29:51 +0000 Subject: [PATCH 25/32] Removed whitespace. --- src/Avalonia.Controls/ItemsControl.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 2dac97726f..1a57990f75 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -221,7 +221,6 @@ namespace Avalonia.Controls return new ItemContainerGenerator(this); } - /// /// Called when new containers are materialized for the by its /// . From 525d1369a5be3ad934b2d7d98c6427d3a6b5792d Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Nov 2016 22:31:22 +0000 Subject: [PATCH 26/32] Removed casting that was not needed. --- src/Avalonia.Controls/ItemsControl.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 1a57990f75..b8c1b46055 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -247,7 +247,7 @@ namespace Avalonia.Controls if (containerControl.Child is ILogical) { - LogicalChildren.Add(containerControl.Child as ILogical); + LogicalChildren.Add(containerControl.Child); } } } @@ -280,7 +280,7 @@ namespace Avalonia.Controls if (containerControl != null && containerControl.Child is ILogical) { - toRemove.Add(containerControl.Child as ILogical); + toRemove.Add(containerControl.Child); ((ISetLogicalParent)containerControl).SetParent(null); } } From ed05f842c00fae30e7d86253a36026e3961b1356 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Nov 2016 22:33:33 +0000 Subject: [PATCH 27/32] Corrected order of Assert arguments. --- tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs index b6a0ca2436..e88d1881e6 100644 --- a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs @@ -85,7 +85,7 @@ namespace Avalonia.Controls.UnitTests var container = (ContentPresenter)target.Presenter.Panel.Children[0]; - Assert.Equal(container.Child.Parent, container); + Assert.Equal(container, container.Child.Parent); } } From 2004bdb329ddb3c5444d43304976c5d172a5789a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Nov 2016 22:35:53 +0000 Subject: [PATCH 28/32] more whitespace changes. --- src/Avalonia.Controls/ItemsControl.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index b8c1b46055..5eb5154f65 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -14,8 +14,6 @@ using Avalonia.Controls.Templates; using Avalonia.Controls.Utils; using Avalonia.LogicalTree; using Avalonia.Metadata; -using System; - namespace Avalonia.Controls { From 225148fd040a891e8efddcd5e8980220f36f67b5 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Nov 2016 22:36:39 +0000 Subject: [PATCH 29/32] Removed unused using. --- src/Avalonia.Controls/ItemsControl.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 5eb5154f65..92a55c1728 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -4,7 +4,6 @@ using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; -using System.Diagnostics.CodeAnalysis; using System.Linq; using Avalonia.Collections; using Avalonia.Controls.Generators; From 67a99dc09a9ca4597cfe9de48664083bf3eb07a4 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Nov 2016 22:42:12 +0000 Subject: [PATCH 30/32] No longer type checking as not necessary. --- src/Avalonia.Controls/ItemsControl.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 92a55c1728..ca1858cc65 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -242,10 +242,7 @@ namespace Avalonia.Controls containerControl.UpdateChild(); - if (containerControl.Child is ILogical) - { - LogicalChildren.Add(containerControl.Child); - } + LogicalChildren.Add(containerControl.Child); } } else @@ -275,7 +272,7 @@ namespace Avalonia.Controls { var containerControl = container.ContainerControl as ContentPresenter; - if (containerControl != null && containerControl.Child is ILogical) + if (containerControl != null) { toRemove.Add(containerControl.Child); ((ISetLogicalParent)containerControl).SetParent(null); From 0b3db9af23bd8caaf2b06092ac43539b01645bda Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Nov 2016 22:49:19 +0000 Subject: [PATCH 31/32] Remove allocation of list that is not neccesary --- src/Avalonia.Controls/ItemsControl.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index ca1858cc65..67f726d056 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -260,8 +260,6 @@ namespace Avalonia.Controls /// The details of the containers. protected virtual void OnContainersDematerialized(ItemContainerEventArgs e) { - var toRemove = new List(); - foreach (var container in e.Containers) { // If the item is its own container, then it will be removed from the logical tree @@ -274,18 +272,16 @@ namespace Avalonia.Controls if (containerControl != null) { - toRemove.Add(containerControl.Child); ((ISetLogicalParent)containerControl).SetParent(null); + LogicalChildren.Remove(containerControl.Child); } } else { - toRemove.Add(container.ContainerControl); + LogicalChildren.Remove(container.ContainerControl); } } } - - LogicalChildren.RemoveAll(toRemove); } /// From d3e66eac583080214e241f2464a2c7b73bb33588 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Nov 2016 22:56:47 +0000 Subject: [PATCH 32/32] Fix null check around adding Container.Child to logical children. --- src/Avalonia.Controls/ItemsControl.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 67f726d056..5d12c9963f 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -242,7 +242,10 @@ namespace Avalonia.Controls containerControl.UpdateChild(); - LogicalChildren.Add(containerControl.Child); + if (containerControl.Child != null) + { + LogicalChildren.Add(containerControl.Child); + } } } else @@ -273,7 +276,11 @@ namespace Avalonia.Controls if (containerControl != null) { ((ISetLogicalParent)containerControl).SetParent(null); - LogicalChildren.Remove(containerControl.Child); + + if (containerControl.Child != null) + { + LogicalChildren.Remove(containerControl.Child); + } } } else