From e5cac827b18c00e06dbe9c0088225994b7259e82 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 Oct 2018 09:39:52 +0200 Subject: [PATCH 1/2] Make TemplatedParent a direct property. During initial layout, `TemplatedParent` is read tens of thousands of times. This being a styled property that used `inherits: true` meant that it was showing up in profiling as taking up a significant amount of time. Make `TemplatedParent` a direct property so that reading it is a simple property access. This doesn't actually complicate the code much at all as once set the property value doesn't change, so `inherited: true` semantics are not that important. --- src/Avalonia.Controls/ItemsControl.cs | 2 -- .../Primitives/TemplatedControl.cs | 19 ++++++++++++++++++- .../Templates/TemplateExtensions.cs | 6 ++++-- src/Avalonia.Styling/StyledElement.cs | 12 ++++++++---- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 9d4cbb9260..d74078c712 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -249,8 +249,6 @@ namespace Avalonia.Controls if (containerControl != null) { ((ISetLogicalParent)containerControl).SetParent(this); - containerControl.SetValue(TemplatedParentProperty, null); - containerControl.UpdateChild(); if (containerControl.Child != null) diff --git a/src/Avalonia.Controls/Primitives/TemplatedControl.cs b/src/Avalonia.Controls/Primitives/TemplatedControl.cs index 296134ca48..ba4c5027d0 100644 --- a/src/Avalonia.Controls/Primitives/TemplatedControl.cs +++ b/src/Avalonia.Controls/Primitives/TemplatedControl.cs @@ -260,7 +260,7 @@ namespace Avalonia.Controls.Primitives var child = template.Build(this); var nameScope = new NameScope(); NameScope.SetNameScope((Control)child, nameScope); - child.SetValue(TemplatedParentProperty, this); + ApplyTemplatedParent(child); RegisterNames(child, nameScope); ((ISetLogicalParent)child).SetParent(this); VisualChildren.Add(child); @@ -326,6 +326,23 @@ namespace Avalonia.Controls.Primitives InvalidateMeasure(); } + /// + /// Sets the TemplatedParent property for the created template children. + /// + /// The control. + private void ApplyTemplatedParent(IControl control) + { + control.SetValue(TemplatedParentProperty, this); + + foreach (var child in control.LogicalChildren) + { + if (child is IControl c) + { + ApplyTemplatedParent(c); + } + } + } + /// /// Registers each control with its name scope. /// diff --git a/src/Avalonia.Controls/Templates/TemplateExtensions.cs b/src/Avalonia.Controls/Templates/TemplateExtensions.cs index 09da737836..18c8bfdeda 100644 --- a/src/Avalonia.Controls/Templates/TemplateExtensions.cs +++ b/src/Avalonia.Controls/Templates/TemplateExtensions.cs @@ -24,12 +24,14 @@ namespace Avalonia.Controls.Templates { foreach (IControl child in control.GetVisualChildren()) { - if (child.TemplatedParent == templatedParent) + var childTemplatedParent = child.TemplatedParent; + + if (childTemplatedParent == templatedParent) { yield return child; } - if (child.TemplatedParent != null) + if (childTemplatedParent != null) { foreach (var descendant in GetTemplateChildren(child, templatedParent)) { diff --git a/src/Avalonia.Styling/StyledElement.cs b/src/Avalonia.Styling/StyledElement.cs index 3d0c840040..e52a1961ba 100644 --- a/src/Avalonia.Styling/StyledElement.cs +++ b/src/Avalonia.Styling/StyledElement.cs @@ -49,8 +49,11 @@ namespace Avalonia /// /// Defines the property. /// - public static readonly StyledProperty TemplatedParentProperty = - AvaloniaProperty.Register(nameof(TemplatedParent), inherits: true); + public static readonly DirectProperty TemplatedParentProperty = + AvaloniaProperty.RegisterDirect( + nameof(TemplatedParent), + o => o.TemplatedParent, + (o ,v) => o.TemplatedParent = v); private int _initCount; private string _name; @@ -62,6 +65,7 @@ namespace Avalonia private Styles _styles; private bool _styled; private Subject _styleDetach = new Subject(); + private ITemplatedControl _templatedParent; private bool _dataContextUpdating; /// @@ -269,8 +273,8 @@ namespace Avalonia /// public ITemplatedControl TemplatedParent { - get { return GetValue(TemplatedParentProperty); } - internal set { SetValue(TemplatedParentProperty, value); } + get => _templatedParent; + internal set => SetAndRaise(TemplatedParentProperty, ref _templatedParent, value); } /// From 44e12491eab44ca65673f83b594f1c558b68e1f8 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 Oct 2018 09:40:08 +0200 Subject: [PATCH 2/2] Ignore Avalonia.Native in ncrunch. --- .ncrunch/Avalonia.Native.v3.ncrunchproject | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .ncrunch/Avalonia.Native.v3.ncrunchproject diff --git a/.ncrunch/Avalonia.Native.v3.ncrunchproject b/.ncrunch/Avalonia.Native.v3.ncrunchproject new file mode 100644 index 0000000000..319cd523ce --- /dev/null +++ b/.ncrunch/Avalonia.Native.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file