Browse Source

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.
pull/2085/head
Steven Kirk 7 years ago
parent
commit
e5cac827b1
  1. 2
      src/Avalonia.Controls/ItemsControl.cs
  2. 19
      src/Avalonia.Controls/Primitives/TemplatedControl.cs
  3. 6
      src/Avalonia.Controls/Templates/TemplateExtensions.cs
  4. 12
      src/Avalonia.Styling/StyledElement.cs

2
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)

19
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();
}
/// <summary>
/// Sets the TemplatedParent property for the created template children.
/// </summary>
/// <param name="control">The control.</param>
private void ApplyTemplatedParent(IControl control)
{
control.SetValue(TemplatedParentProperty, this);
foreach (var child in control.LogicalChildren)
{
if (child is IControl c)
{
ApplyTemplatedParent(c);
}
}
}
/// <summary>
/// Registers each control with its name scope.
/// </summary>

6
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))
{

12
src/Avalonia.Styling/StyledElement.cs

@ -49,8 +49,11 @@ namespace Avalonia
/// <summary>
/// Defines the <see cref="TemplatedParent"/> property.
/// </summary>
public static readonly StyledProperty<ITemplatedControl> TemplatedParentProperty =
AvaloniaProperty.Register<StyledElement, ITemplatedControl>(nameof(TemplatedParent), inherits: true);
public static readonly DirectProperty<StyledElement, ITemplatedControl> TemplatedParentProperty =
AvaloniaProperty.RegisterDirect<StyledElement, ITemplatedControl>(
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<IStyleable> _styleDetach = new Subject<IStyleable>();
private ITemplatedControl _templatedParent;
private bool _dataContextUpdating;
/// <summary>
@ -269,8 +273,8 @@ namespace Avalonia
/// </summary>
public ITemplatedControl TemplatedParent
{
get { return GetValue(TemplatedParentProperty); }
internal set { SetValue(TemplatedParentProperty, value); }
get => _templatedParent;
internal set => SetAndRaise(TemplatedParentProperty, ref _templatedParent, value);
}
/// <summary>

Loading…
Cancel
Save