| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066 | 
							- using System;
 
- using System.Collections;
 
- using System.Collections.Generic;
 
- using System.Collections.Specialized;
 
- using System.ComponentModel;
 
- using System.Diagnostics;
 
- using System.Linq;
 
- using Avalonia.Animation;
 
- using Avalonia.Collections;
 
- using Avalonia.Controls;
 
- using Avalonia.Data;
 
- using Avalonia.Diagnostics;
 
- using Avalonia.Logging;
 
- using Avalonia.LogicalTree;
 
- using Avalonia.PropertyStore;
 
- using Avalonia.Styling;
 
- namespace Avalonia
 
- {
 
-     /// <summary>
 
-     /// Extends an <see cref="Animatable"/> with the following features:
 
-     /// 
 
-     /// - An inherited <see cref="DataContext"/>.
 
-     /// - Implements <see cref="IStyleable"/> to allow styling to work on the styled element.
 
-     /// - Implements <see cref="ILogical"/> to form part of a logical tree.
 
-     /// - A collection of class strings for custom styling.
 
-     /// </summary>
 
-     public class StyledElement : Animatable, 
 
-         IDataContextProvider, 
 
-         ILogical,
 
-         IThemeVariantHost,
 
-         IStyleHost,
 
-         IStyleable,
 
-         ISetLogicalParent,
 
-         ISetInheritanceParent,
 
-         ISupportInitialize
 
-     {
 
-         /// <summary>
 
-         /// Defines the <see cref="DataContext"/> property.
 
-         /// </summary>
 
-         public static readonly StyledProperty<object?> DataContextProperty =
 
-             AvaloniaProperty.Register<StyledElement, object?>(
 
-                 nameof(DataContext),
 
-                 defaultValue: null,
 
-                 inherits: true,
 
-                 defaultBindingMode: BindingMode.OneWay,
 
-                 validate: null,
 
-                 coerce: null,
 
-                 enableDataValidation: false,
 
-                 notifying: DataContextNotifying);
 
-         /// <summary>
 
-         /// Defines the <see cref="Name"/> property.
 
-         /// </summary>
 
-         public static readonly DirectProperty<StyledElement, string?> NameProperty =
 
-             AvaloniaProperty.RegisterDirect<StyledElement, string?>(nameof(Name), o => o.Name, (o, v) => o.Name = v);
 
-         
 
-         /// <summary>
 
-         /// Defines the <see cref="Parent"/> property.
 
-         /// </summary>
 
-         public static readonly DirectProperty<StyledElement, StyledElement?> ParentProperty =
 
-             AvaloniaProperty.RegisterDirect<StyledElement, StyledElement?>(nameof(Parent), o => o.Parent);
 
-         /// <summary>
 
-         /// Defines the <see cref="TemplatedParent"/> property.
 
-         /// </summary>
 
-         public static readonly DirectProperty<StyledElement, AvaloniaObject?> TemplatedParentProperty =
 
-             AvaloniaProperty.RegisterDirect<StyledElement, AvaloniaObject?>(
 
-                 nameof(TemplatedParent),
 
-                 o => o.TemplatedParent);
 
-         
 
-         /// <summary>
 
-         /// Defines the <see cref="Theme"/> property.
 
-         /// </summary>
 
-         public static readonly StyledProperty<ControlTheme?> ThemeProperty =
 
-             AvaloniaProperty.Register<StyledElement, ControlTheme?>(nameof(Theme));
 
-         private static readonly ControlTheme s_invalidTheme = new ControlTheme();
 
-         private int _initCount;
 
-         private string? _name;
 
-         private readonly Classes _classes = new Classes();
 
-         private ILogicalRoot? _logicalRoot;
 
-         private IAvaloniaList<ILogical>? _logicalChildren;
 
-         private IResourceDictionary? _resources;
 
-         private Styles? _styles;
 
-         private bool _stylesApplied;
 
-         private bool _themeApplied;
 
-         private bool _templatedParentThemeApplied;
 
-         private AvaloniaObject? _templatedParent;
 
-         private bool _dataContextUpdating;
 
-         private ControlTheme? _implicitTheme;
 
-         /// <summary>
 
-         /// Initializes static members of the <see cref="StyledElement"/> class.
 
-         /// </summary>
 
-         static StyledElement()
 
-         {
 
-             DataContextProperty.Changed.AddClassHandler<StyledElement>((x,e) => x.OnDataContextChangedCore(e));
 
-         }
 
-         /// <summary>
 
-         /// Initializes a new instance of the <see cref="StyledElement"/> class.
 
-         /// </summary>
 
-         public StyledElement()
 
-         {
 
-             _logicalRoot = this as ILogicalRoot;
 
-         }
 
-         /// <summary>
 
-         /// Raised when the styled element is attached to a rooted logical tree.
 
-         /// </summary>
 
-         public event EventHandler<LogicalTreeAttachmentEventArgs>? AttachedToLogicalTree;
 
-         /// <summary>
 
-         /// Raised when the styled element is detached from a rooted logical tree.
 
-         /// </summary>
 
-         public event EventHandler<LogicalTreeAttachmentEventArgs>? DetachedFromLogicalTree;
 
-         /// <summary>
 
-         /// Occurs when the <see cref="DataContext"/> property changes.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// This event will be raised when the <see cref="DataContext"/> property has changed and
 
-         /// all subscribers to that change have been notified.
 
-         /// </remarks>
 
-         public event EventHandler? DataContextChanged;
 
-         /// <summary>
 
-         /// Occurs when the styled element has finished initialization.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// The Initialized event indicates that all property values on the styled element have been set.
 
-         /// When loading the styled element from markup, it occurs when 
 
-         /// <see cref="ISupportInitialize.EndInit"/> is called *and* the styled element
 
-         /// is attached to a rooted logical tree. When the styled element is created by code and
 
-         /// <see cref="ISupportInitialize"/> is not used, it is called when the styled element is attached
 
-         /// to the visual tree.
 
-         /// </remarks>
 
-         public event EventHandler? Initialized;
 
-         /// <summary>
 
-         /// Occurs when a resource in this styled element or a parent styled element has changed.
 
-         /// </summary>
 
-         public event EventHandler<ResourcesChangedEventArgs>? ResourcesChanged;
 
-         /// <inheritdoc />
 
-         public event EventHandler? ActualThemeVariantChanged;
 
-         
 
-         /// <summary>
 
-         /// Gets or sets the name of the styled element.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// An element's name is used to uniquely identify an element within the element's name
 
-         /// scope. Once the element is added to a logical tree, its name cannot be changed.
 
-         /// </remarks>
 
-         public string? Name
 
-         {
 
-             get => _name;
 
-             set
 
-             {
 
-                 if (_stylesApplied)
 
-                 {
 
-                     throw new InvalidOperationException("Cannot set Name : styled element already styled.");
 
-                 }
 
-                 _name = value;
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Gets or sets the styled element's classes.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// <para>
 
-         /// Classes can be used to apply user-defined styling to styled elements, or to allow styled elements
 
-         /// that share a common purpose to be easily selected.
 
-         /// </para>
 
-         /// <para>
 
-         /// Even though this property can be set, the setter is only intended for use in object
 
-         /// initializers. Assigning to this property does not change the underlying collection,
 
-         /// it simply clears the existing collection and adds the contents of the assigned
 
-         /// collection.
 
-         /// </para>
 
-         /// </remarks>
 
-         public Classes Classes
 
-         {
 
-             get
 
-             {
 
-                 return _classes;
 
-             }
 
-             set
 
-             {
 
-                 if (_classes != value)
 
-                 {
 
-                     _classes.Replace(value);
 
-                 }
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Gets or sets the control's data context.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// The data context is an inherited property that specifies the default object that will
 
-         /// be used for data binding.
 
-         /// </remarks>
 
-         public object? DataContext
 
-         {
 
-             get { return GetValue(DataContextProperty); }
 
-             set { SetValue(DataContextProperty, value); }
 
-         }
 
-         /// <summary>
 
-         /// Gets a value that indicates whether the element has finished initialization.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// For more information about when IsInitialized is set, see the <see cref="Initialized"/>
 
-         /// event.
 
-         /// </remarks>
 
-         public bool IsInitialized { get; private set; }
 
-         /// <summary>
 
-         /// Gets the styles for the styled element.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// Styles for the entire application are added to the Application.Styles collection, but
 
-         /// each styled element may in addition define its own styles which are applied to the styled element
 
-         /// itself and its children.
 
-         /// </remarks>
 
-         public Styles Styles => _styles ??= new Styles(this);
 
-         /// <summary>
 
-         /// Gets or sets the styled element's resource dictionary.
 
-         /// </summary>
 
-         public IResourceDictionary Resources
 
-         {
 
-             get => _resources ??= new ResourceDictionary(this);
 
-             set
 
-             {
 
-                 value = value ?? throw new ArgumentNullException(nameof(value));
 
-                 _resources?.RemoveOwner(this);
 
-                 _resources = value;
 
-                 _resources.AddOwner(this);
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Gets the styled element whose lookless template this styled element is part of.
 
-         /// </summary>
 
-         public AvaloniaObject? TemplatedParent
 
-         {
 
-             get => _templatedParent;
 
-             internal set => SetAndRaise(TemplatedParentProperty, ref _templatedParent, value);
 
-         }
 
-         /// <summary>
 
-         /// Gets or sets the theme to be applied to the element.
 
-         /// </summary>
 
-         public ControlTheme? Theme
 
-         {
 
-             get => GetValue(ThemeProperty);
 
-             set => SetValue(ThemeProperty, value);
 
-         }
 
-         /// <summary>
 
-         /// Gets the styled element's logical children.
 
-         /// </summary>
 
-         protected internal IAvaloniaList<ILogical> LogicalChildren
 
-         {
 
-             get
 
-             {
 
-                 if (_logicalChildren == null)
 
-                 {
 
-                     var list = new AvaloniaList<ILogical>
 
-                     {
 
-                         ResetBehavior = ResetBehavior.Remove,
 
-                         Validate = logical => ValidateLogicalChild(logical)
 
-                     };
 
-                     list.CollectionChanged += LogicalChildrenCollectionChanged;
 
-                     _logicalChildren = list;
 
-                 }
 
-                 return _logicalChildren;
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Gets the <see cref="Classes"/> collection in a form that allows adding and removing
 
-         /// pseudoclasses.
 
-         /// </summary>
 
-         protected IPseudoClasses PseudoClasses => Classes;
 
-         /// <summary>
 
-         /// Gets a value indicating whether the element is attached to a rooted logical tree.
 
-         /// </summary>
 
-         bool ILogical.IsAttachedToLogicalTree => _logicalRoot != null;
 
-         /// <summary>
 
-         /// Gets the styled element's logical parent.
 
-         /// </summary>
 
-         public StyledElement? Parent { get; private set; }
 
-         /// <inheritdoc />
 
-         public ThemeVariant ActualThemeVariant => GetValue(ThemeVariant.ActualThemeVariantProperty);
 
-         
 
-         /// <summary>
 
-         /// Gets the styled element's logical parent.
 
-         /// </summary>
 
-         ILogical? ILogical.LogicalParent => Parent;
 
-         /// <summary>
 
-         /// Gets the styled element's logical children.
 
-         /// </summary>
 
-         IAvaloniaReadOnlyList<ILogical> ILogical.LogicalChildren => LogicalChildren;
 
-         /// <inheritdoc/>
 
-         bool IResourceNode.HasResources => (_resources?.HasResources ?? false) ||
 
-             (((IResourceNode?)_styles)?.HasResources ?? false);
 
-         /// <inheritdoc/>
 
-         IAvaloniaReadOnlyList<string> IStyleable.Classes => Classes;
 
-         /// <summary>
 
-         /// Gets the type by which the styled element is styled.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// Usually controls are styled by their own type, but there are instances where you want
 
-         /// a styled element to be styled by its base type, e.g. creating SpecialButton that
 
-         /// derives from Button and adds extra functionality but is still styled as a regular
 
-         /// Button.
 
-         /// </remarks>
 
-         Type IStyleable.StyleKey => GetType();
 
-         /// <inheritdoc/>
 
-         bool IStyleHost.IsStylesInitialized => _styles != null;
 
-         /// <inheritdoc/>
 
-         IStyleHost? IStyleHost.StylingParent => (IStyleHost?)InheritanceParent;
 
-         /// <inheritdoc/>
 
-         public virtual void BeginInit()
 
-         {
 
-             ++_initCount;
 
-         }
 
-         /// <inheritdoc/>
 
-         public virtual void EndInit()
 
-         {
 
-             if (_initCount == 0)
 
-             {
 
-                 throw new InvalidOperationException("BeginInit was not called.");
 
-             }
 
-             if (--_initCount == 0 && _logicalRoot is not null)
 
-             {
 
-                 ApplyStyling();
 
-                 InitializeIfNeeded();
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Applies styling to the control if the control is initialized and styling is not
 
-         /// already applied.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// The styling system will automatically apply styling when required, so it should not
 
-         /// usually be necessary to call this method manually.
 
-         /// </remarks>
 
-         /// <returns>
 
-         /// A value indicating whether styling is now applied to the control.
 
-         /// </returns>
 
-         public bool ApplyStyling()
 
-         {
 
-             if (_initCount == 0 && (!_stylesApplied || !_themeApplied || !_templatedParentThemeApplied))
 
-             {
 
-                 GetValueStore().BeginStyling();
 
-                 try
 
-                 {
 
-                     if (!_themeApplied)
 
-                     {
 
-                         ApplyControlTheme();
 
-                         _themeApplied = true;
 
-                     }
 
-                     if (!_templatedParentThemeApplied)
 
-                     {
 
-                         ApplyTemplatedParentControlTheme();
 
-                         _templatedParentThemeApplied = true;
 
-                     }
 
-                     if (!_stylesApplied)
 
-                     {
 
-                         ApplyStyles(this);
 
-                         _stylesApplied = true;
 
-                     }
 
-                 }
 
-                 finally
 
-                 {
 
-                     GetValueStore().EndStyling();
 
-                 }
 
-             }
 
-             return _stylesApplied;
 
-         }
 
-         protected void InitializeIfNeeded()
 
-         {
 
-             if (_initCount == 0 && !IsInitialized)
 
-             {
 
-                 IsInitialized = true;
 
-                 OnInitialized();
 
-                 Initialized?.Invoke(this, EventArgs.Empty);
 
-             }
 
-         }
 
-         internal StyleDiagnostics GetStyleDiagnosticsInternal()
 
-         {
 
-             var styles = new List<IStyleInstance>();
 
-             foreach (var frame in GetValueStore().Frames)
 
-             {
 
-                 if (frame is IStyleInstance style)
 
-                     styles.Add(style);
 
-             }
 
-             return new StyleDiagnostics(styles);
 
-         }
 
-         /// <inheritdoc/>
 
-         void ILogical.NotifyAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
 
-         {
 
-             OnAttachedToLogicalTreeCore(e);
 
-         }
 
-         /// <inheritdoc/>
 
-         void ILogical.NotifyDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
 
-         {
 
-             OnDetachedFromLogicalTreeCore(e);
 
-         }
 
-         /// <inheritdoc/>
 
-         void ILogical.NotifyResourcesChanged(ResourcesChangedEventArgs e) => NotifyResourcesChanged(e);
 
-         /// <inheritdoc/>
 
-         void IResourceHost.NotifyHostedResourcesChanged(ResourcesChangedEventArgs e) => NotifyResourcesChanged(e);
 
-         /// <inheritdoc/>
 
-         public bool TryGetResource(object key, ThemeVariant? theme, out object? value)
 
-         {
 
-             value = null;
 
-             return (_resources?.TryGetResource(key, theme, out value) ?? false) ||
 
-                    (_styles?.TryGetResource(key, theme, out value) ?? false);
 
-         }
 
-         /// <summary>
 
-         /// Sets the styled element's logical parent.
 
-         /// </summary>
 
-         /// <param name="parent">The parent.</param>
 
-         void ISetLogicalParent.SetParent(ILogical? parent)
 
-         {
 
-             var old = Parent;
 
-             if (parent != old)
 
-             {
 
-                 if (old != null && parent != null)
 
-                 {
 
-                     throw new InvalidOperationException("The Control already has a parent.");
 
-                 }
 
-                 if (InheritanceParent == null || parent == null)
 
-                 {
 
-                     InheritanceParent = parent as AvaloniaObject;
 
-                 }
 
-                 Parent = (StyledElement?)parent;
 
-                 if (_logicalRoot != null)
 
-                 {
 
-                     var e = new LogicalTreeAttachmentEventArgs(_logicalRoot, this, old!);
 
-                     OnDetachedFromLogicalTreeCore(e);
 
-                 }
 
-                 var newRoot = FindLogicalRoot(this);
 
-                 if (newRoot is object)
 
-                 {
 
-                     var e = new LogicalTreeAttachmentEventArgs(newRoot, this, parent!);
 
-                     OnAttachedToLogicalTreeCore(e);
 
-                 }
 
-                 else if (parent is null)
 
-                 {
 
-                     // If we were attached to the logical tree, we piggyback on the tree traversal
 
-                     // there to raise resources changed notifications. If we're being removed from
 
-                     // the logical tree, then traverse the tree raising notifications now.
 
-                     //
 
-                     // We don't raise resources changed notifications if we're being attached to a 
 
-                     // non-rooted control beacuse it's unlikely that dynamic resources need to be 
 
-                     // correct until the control is added to the tree, and it causes a *lot* of
 
-                     // notifications.
 
-                     NotifyResourcesChanged();
 
-                 }
 
-                 RaisePropertyChanged(ParentProperty, old, Parent);
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Sets the styled element's inheritance parent.
 
-         /// </summary>
 
-         /// <param name="parent">The parent.</param>
 
-         void ISetInheritanceParent.SetParent(AvaloniaObject? parent)
 
-         {
 
-             InheritanceParent = parent;
 
-         }
 
-         void IStyleHost.StylesAdded(IReadOnlyList<IStyle> styles)
 
-         {
 
-             if (HasSettersOrAnimations(styles))
 
-                 InvalidateStyles(recurse: true);
 
-         }
 
-         void IStyleHost.StylesRemoved(IReadOnlyList<IStyle> styles)
 
-         {
 
-             if (FlattenStyles(styles) is { } allStyles)
 
-                 DetachStyles(allStyles);
 
-         }
 
-         protected virtual void LogicalChildrenCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
 
-         {
 
-             switch (e.Action)
 
-             {
 
-                 case NotifyCollectionChangedAction.Add:
 
-                     SetLogicalParent(e.NewItems!);
 
-                     break;
 
-                 case NotifyCollectionChangedAction.Remove:
 
-                     ClearLogicalParent(e.OldItems!);
 
-                     break;
 
-                 case NotifyCollectionChangedAction.Replace:
 
-                     ClearLogicalParent(e.OldItems!);
 
-                     SetLogicalParent(e.NewItems!);
 
-                     break;
 
-                 case NotifyCollectionChangedAction.Reset:
 
-                     throw new NotSupportedException("Reset should not be signaled on LogicalChildren collection");
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Notifies child controls that a change has been made to resources that apply to them.
 
-         /// </summary>
 
-         /// <param name="e">The event args.</param>
 
-         protected virtual void NotifyChildResourcesChanged(ResourcesChangedEventArgs e)
 
-         {
 
-             if (_logicalChildren is object)
 
-             {
 
-                 var count = _logicalChildren.Count;
 
-                 if (count > 0)
 
-                 {
 
-                     e ??= ResourcesChangedEventArgs.Empty;
 
-                     for (var i = 0; i < count; ++i)
 
-                     {
 
-                         _logicalChildren[i].NotifyResourcesChanged(e);
 
-                     }
 
-                 }
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Called when the styled element is added to a rooted logical tree.
 
-         /// </summary>
 
-         /// <param name="e">The event args.</param>
 
-         protected virtual void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
 
-         {
 
-         }
 
-         /// <summary>
 
-         /// Called when the styled element is removed from a rooted logical tree.
 
-         /// </summary>
 
-         /// <param name="e">The event args.</param>
 
-         protected virtual void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
 
-         {
 
-         }
 
-         /// <summary>
 
-         /// Called when the <see cref="DataContext"/> property changes.
 
-         /// </summary>
 
-         /// <param name="e">The event args.</param>
 
-         protected virtual void OnDataContextChanged(EventArgs e)
 
-         {
 
-             DataContextChanged?.Invoke(this, EventArgs.Empty);
 
-         }
 
-         /// <summary>
 
-         /// Called when the <see cref="DataContext"/> begins updating.
 
-         /// </summary>
 
-         protected virtual void OnDataContextBeginUpdate()
 
-         {
 
-         }
 
-         /// <summary>
 
-         /// Called when the <see cref="DataContext"/> finishes updating.
 
-         /// </summary>
 
-         protected virtual void OnDataContextEndUpdate()
 
-         {
 
-         }
 
-         /// <summary>
 
-         /// Called when the control finishes initialization.
 
-         /// </summary>
 
-         protected virtual void OnInitialized()
 
-         {
 
-         }
 
-         protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
 
-         {
 
-             base.OnPropertyChanged(change);
 
-             if (change.Property == ThemeProperty)
 
-             {
 
-                 OnControlThemeChanged();
 
-             }
 
-             else if (change.Property == ThemeVariant.RequestedThemeVariantProperty)
 
-             {
 
-                 if (change.GetNewValue<ThemeVariant>() is {} themeVariant && themeVariant != ThemeVariant.Default)
 
-                     SetValue(ThemeVariant.ActualThemeVariantProperty, themeVariant);
 
-                 else
 
-                     ClearValue(ThemeVariant.ActualThemeVariantProperty);
 
-             }
 
-             else if (change.Property == ThemeVariant.ActualThemeVariantProperty)
 
-             {
 
-                 ActualThemeVariantChanged?.Invoke(this, EventArgs.Empty);
 
-             }
 
-         }
 
-         private protected virtual void OnControlThemeChanged()
 
-         {
 
-             var values = GetValueStore();
 
-             values.BeginStyling();
 
-             try 
 
-             { 
 
-                 values.RemoveFrames(FrameType.Theme);
 
-             }
 
-             finally 
 
-             { 
 
-                 values.EndStyling();
 
-                 _themeApplied = false;
 
-             }
 
-         }
 
-         internal virtual void OnTemplatedParentControlThemeChanged()
 
-         {
 
-             var values = GetValueStore();
 
-             values.BeginStyling();
 
-             try 
 
-             { 
 
-                 values.RemoveFrames(FrameType.TemplatedParentTheme); 
 
-             }
 
-             finally 
 
-             { 
 
-                 values.EndStyling();
 
-                 _templatedParentThemeApplied = false;
 
-             }
 
-         }
 
-         internal ControlTheme? GetEffectiveTheme()
 
-         {
 
-             var theme = Theme;
 
-             // Explicitly set Theme property takes precedence.
 
-             if (theme is not null)
 
-                 return theme;
 
-             // If the Theme property is not set, try to find a ControlTheme resource with our StyleKey.
 
-             if (_implicitTheme is null)
 
-             {
 
-                 var key = ((IStyleable)this).StyleKey;
 
-                 if (this.TryFindResource(key, out var value) && value is ControlTheme t)
 
-                     _implicitTheme = t;
 
-                 else
 
-                     _implicitTheme = s_invalidTheme;
 
-             }
 
-             if (_implicitTheme != s_invalidTheme)
 
-                 return _implicitTheme;
 
-             return null;
 
-         }
 
-         internal virtual void InvalidateStyles(bool recurse)
 
-         {
 
-             var values = GetValueStore();
 
-             values.BeginStyling();
 
-             try { values.RemoveFrames(FrameType.Style); }
 
-             finally { values.EndStyling(); }
 
-             _stylesApplied = false;
 
-             if (recurse && GetInheritanceChildren() is { } children)
 
-             {
 
-                 var childCount = children.Count;
 
-                 for (var i = 0; i < childCount; ++i)
 
-                     (children[i] as StyledElement)?.InvalidateStyles(recurse);
 
-             }
 
-         }
 
-         private static void DataContextNotifying(AvaloniaObject o, bool updateStarted)
 
-         {
 
-             if (o is StyledElement element)
 
-             {
 
-                 DataContextNotifying(element, updateStarted);
 
-             }
 
-         }
 
-         private static void DataContextNotifying(StyledElement element, bool updateStarted)
 
-         {
 
-             if (updateStarted)
 
-             {
 
-                 if (!element._dataContextUpdating)
 
-                 {
 
-                     element._dataContextUpdating = true;
 
-                     element.OnDataContextBeginUpdate();
 
-                     var logicalChildren = element.LogicalChildren;
 
-                     var logicalChildrenCount = logicalChildren.Count;
 
-                     for (var i = 0; i < logicalChildrenCount; i++)
 
-                     {
 
-                         if (element.LogicalChildren[i] is StyledElement s &&
 
-                             s.InheritanceParent == element &&
 
-                             !s.IsSet(DataContextProperty))
 
-                         {
 
-                             DataContextNotifying(s, updateStarted);
 
-                         }
 
-                     }
 
-                 }
 
-             }
 
-             else
 
-             {
 
-                 if (element._dataContextUpdating)
 
-                 {
 
-                     element.OnDataContextEndUpdate();
 
-                     element._dataContextUpdating = false;
 
-                 }
 
-             }
 
-         }
 
-         private static ILogicalRoot? FindLogicalRoot(IStyleHost? e)
 
-         {
 
-             while (e != null)
 
-             {
 
-                 if (e is ILogicalRoot root)
 
-                 {
 
-                     return root;
 
-                 }
 
-                 e = e.StylingParent;
 
-             }
 
-             return null;
 
-         }
 
-         private static void ValidateLogicalChild(ILogical c)
 
-         {
 
-             if (c == null)
 
-             {
 
-                 throw new ArgumentException("Cannot add null to LogicalChildren.");
 
-             }
 
-         }
 
-         private void ApplyControlTheme()
 
-         {
 
-             if (GetEffectiveTheme() is { } theme)
 
-                 ApplyControlTheme(theme, FrameType.Theme);
 
-         }
 
-         private void ApplyTemplatedParentControlTheme()
 
-         {
 
-             if ((TemplatedParent as StyledElement)?.GetEffectiveTheme() is { } parentTheme)
 
-             {
 
-                 ApplyControlTheme(parentTheme, FrameType.TemplatedParentTheme);
 
-             }
 
-         }
 
-         private void ApplyControlTheme(ControlTheme theme, FrameType type)
 
-         {
 
-             Debug.Assert(type is FrameType.Theme or FrameType.TemplatedParentTheme);
 
-             if (theme.BasedOn is ControlTheme basedOn)
 
-                 ApplyControlTheme(basedOn, type);
 
-             theme.TryAttach(this, type);
 
-             if (theme.HasChildren)
 
-             {
 
-                 var children = theme.Children;
 
-                 for (var i = 0; i < children.Count; i++)
 
-                 {
 
-                     ApplyStyle(children[i], null, type);
 
-                 }
 
-             }
 
-         }
 
-         private void ApplyStyles(IStyleHost host)
 
-         {
 
-             var parent = host.StylingParent;
 
-             if (parent != null)
 
-                 ApplyStyles(parent);
 
-             
 
-             if (host.IsStylesInitialized)
 
-             {
 
-                 var styles = host.Styles;
 
-                 for (var i = 0; i < styles.Count; ++i)
 
-                 {
 
-                     ApplyStyle(styles[i], host, FrameType.Style);
 
-                 }
 
-             }
 
-         }
 
-         private void ApplyStyle(IStyle style, IStyleHost? host, FrameType type)
 
-         {
 
-             if (style is Style s)
 
-                 s.TryAttach(this, host, type);
 
-             var children = style.Children;
 
-             for (var i = 0; i < children.Count; i++)
 
-             {
 
-                 ApplyStyle(children[i], host, type);
 
-             }
 
-         }
 
-         private void ReevaluateImplicitTheme()
 
-         {
 
-             // We only need to check if the theme has changed when Theme isn't set (i.e. when we
 
-             // have an implicit theme).
 
-             if (Theme is not null)
 
-                 return;
 
-             // Refetch the implicit theme.
 
-             var oldImplicitTheme = _implicitTheme == s_invalidTheme ? null : _implicitTheme;
 
-             _implicitTheme = null;
 
-             GetEffectiveTheme();
 
-             var newImplicitTheme = _implicitTheme == s_invalidTheme ? null : _implicitTheme;
 
-             // If the implicit theme has changed, detach the existing theme.
 
-             if (newImplicitTheme != oldImplicitTheme)
 
-             {
 
-                 OnControlThemeChanged();
 
-                 _themeApplied = false;
 
-             }
 
-         }
 
-         private void OnAttachedToLogicalTreeCore(LogicalTreeAttachmentEventArgs e)
 
-         {
 
-             if (this.GetLogicalParent() == null && !(this is ILogicalRoot))
 
-             {
 
-                 throw new InvalidOperationException(
 
-                     $"AttachedToLogicalTreeCore called for '{GetType().Name}' but control has no logical parent.");
 
-             }
 
-             // This method can be called when a control is already attached to the logical tree
 
-             // in the following scenario:
 
-             // - ListBox gets assigned Items containing ListBoxItem
 
-             // - ListBox makes ListBoxItem a logical child
 
-             // - ListBox template gets applied; making its Panel get attached to logical tree
 
-             // - That AttachedToLogicalTree signal travels down to the ListBoxItem
 
-             if (_logicalRoot == null)
 
-             {
 
-                 _logicalRoot = e.Root;
 
-                 ReevaluateImplicitTheme();
 
-                 ApplyStyling();
 
-                 NotifyResourcesChanged(propagate: false);
 
-                 OnAttachedToLogicalTree(e);
 
-                 AttachedToLogicalTree?.Invoke(this, e);
 
-             }
 
-             var logicalChildren = LogicalChildren;
 
-             var logicalChildrenCount = logicalChildren.Count;
 
-             for (var i = 0; i < logicalChildrenCount; i++)
 
-             {
 
-                 if (logicalChildren[i] is StyledElement child)
 
-                 {
 
-                     child.OnAttachedToLogicalTreeCore(e);
 
-                 }
 
-             }
 
-         }
 
-         private void OnDetachedFromLogicalTreeCore(LogicalTreeAttachmentEventArgs e)
 
-         {
 
-             if (_logicalRoot != null)
 
-             {
 
-                 _logicalRoot = null;
 
-                 InvalidateStyles(recurse: false);
 
-                 OnDetachedFromLogicalTree(e);
 
-                 DetachedFromLogicalTree?.Invoke(this, e);
 
-                 var logicalChildren = LogicalChildren;
 
-                 var logicalChildrenCount = logicalChildren.Count;
 
-                 for (var i = 0; i < logicalChildrenCount; i++)
 
-                 {
 
-                     if (logicalChildren[i] is StyledElement child)
 
-                     {
 
-                         child.OnDetachedFromLogicalTreeCore(e);
 
-                     }
 
-                 }
 
- #if DEBUG
 
-                 if (((INotifyCollectionChangedDebug)Classes).GetCollectionChangedSubscribers()?.Length > 0)
 
-                 {
 
-                     Logger.TryGet(LogEventLevel.Warning, LogArea.Control)?.Log(
 
-                         this,
 
-                         "{Type} detached from logical tree but still has class listeners",
 
-                         GetType());
 
-                 }
 
- #endif
 
-             }
 
-         }
 
-         private void OnDataContextChangedCore(AvaloniaPropertyChangedEventArgs e)
 
-         {
 
-             OnDataContextChanged(EventArgs.Empty);
 
-         }
 
-         private void SetLogicalParent(IList children)
 
-         {
 
-             var count = children.Count;
 
-             for (var i = 0; i < count; i++)
 
-             {
 
-                 var logical = (ILogical) children[i]!;
 
-                 
 
-                 if (logical.LogicalParent is null)
 
-                 {
 
-                     ((ISetLogicalParent)logical).SetParent(this);
 
-                 }
 
-             }
 
-         }
 
-         private void ClearLogicalParent(IList children)
 
-         {
 
-             var count = children.Count;
 
-             for (var i = 0; i < count; i++)
 
-             {
 
-                 var logical = (ILogical) children[i]!;
 
-                 
 
-                 if (logical.LogicalParent == this)
 
-                 {
 
-                     ((ISetLogicalParent)logical).SetParent(null);
 
-                 }
 
-             }
 
-         }
 
-         private void DetachStyles(IReadOnlyList<Style> styles)
 
-         {
 
-             var values = GetValueStore();
 
-             values.BeginStyling();
 
-             try { values.RemoveFrames(styles); }
 
-             finally { values.EndStyling(); }
 
-             if (_logicalChildren is not null)
 
-             {
 
-                 var childCount = _logicalChildren.Count;
 
-                 for (var i = 0; i < childCount; ++i)
 
-                 {
 
-                     (_logicalChildren[i] as StyledElement)?.DetachStyles(styles);
 
-                 }
 
-             }
 
-         }
 
-         private void NotifyResourcesChanged(
 
-             ResourcesChangedEventArgs? e = null,
 
-             bool propagate = true)
 
-         {
 
-             if (ResourcesChanged is object)
 
-             {
 
-                 e ??= ResourcesChangedEventArgs.Empty;
 
-                 ResourcesChanged(this, e);
 
-             }
 
-             if (propagate)
 
-             {
 
-                 e ??= ResourcesChangedEventArgs.Empty;
 
-                 NotifyChildResourcesChanged(e);
 
-             }
 
-         }
 
-         private static IReadOnlyList<Style>? FlattenStyles(IReadOnlyList<IStyle> styles)
 
-         {
 
-             List<Style>? result = null;
 
-             static void FlattenStyle(IStyle style, ref List<Style>? result)
 
-             {
 
-                 if (style is Style s)
 
-                     (result ??= new()).Add(s);
 
-                 FlattenStyles(style.Children, ref result);
 
-             }
 
-             static void FlattenStyles(IReadOnlyList<IStyle> styles, ref List<Style>? result)
 
-             {
 
-                 var count = styles.Count;
 
-                 for (var i = 0; i < count; ++i)
 
-                     FlattenStyle(styles[i], ref result);
 
-             }
 
-             FlattenStyles(styles, ref result);
 
-             return result;
 
-         }
 
-         private static bool HasSettersOrAnimations(IReadOnlyList<IStyle> styles)
 
-         {
 
-             static bool StyleHasSettersOrAnimations(IStyle style)
 
-             {
 
-                 if (style is StyleBase s && s.HasSettersOrAnimations)
 
-                     return true;
 
-                 return HasSettersOrAnimations(style.Children);
 
-             }
 
-             var count = styles.Count;
 
-             for (var i = 0; i < count; ++i)
 
-             {
 
-                 if (StyleHasSettersOrAnimations(styles[i]))
 
-                     return true;
 
-             }
 
-             return false;
 
-         }
 
-         private static IReadOnlyList<StyleBase> RecurseStyles(IReadOnlyList<IStyle> styles)
 
-         {
 
-             var result = new List<StyleBase>();
 
-             RecurseStyles(styles, result);
 
-             return result;
 
-         }
 
-         private static void RecurseStyles(IReadOnlyList<IStyle> styles, List<StyleBase> result)
 
-         {
 
-             var count = styles.Count;
 
-             for (var i = 0; i < count; ++i)
 
-             {
 
-                 var s = styles[i];
 
-                 if (s is StyleBase style)
 
-                     result.Add(style);
 
-                 else if (s is IReadOnlyList<IStyle> children)
 
-                     RecurseStyles(children, result);
 
-             }
 
-         }
 
-     }
 
- }
 
 
  |