private void RegisterWithNameScope() { if (_nameScope == null) { _nameScope = NameScope.GetNameScope(this) ?? ((Control)Parent)?._nameScope; } if (Name != null) { _nameScope?.Register(Name, this); var visualParent = Parent as Visual; if (this is INameScope && visualParent != null) { // If we have e.g. a named UserControl in a window then we want that control // to be findable by name from the Window, so register with both name scopes. // This differs from WPF's behavior in that XAML manually registers controls // with name scopes based on the XAML file in which the name attribute appears, // but we're trying to avoid XAML magic in Avalonia in order to made code- // created UIs easy. This will cause problems if a UserControl declares a name // in its XAML and that control is included multiple times in a parent control // (as the name will be duplicated), however at the moment I'm fine with saying // "don't do that". var parentNameScope = NameScope.FindNameScope(visualParent); parentNameScope?.Register(Name, this); } } }
/// <summary> /// Called when the control is added to a logical tree. /// </summary> /// <param name="e">The event args.</param> /// <remarks> /// It is vital that if you override this method you call the base implementation; /// failing to do so will cause numerous features to not work as expected. /// </remarks> protected virtual void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) { // 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 (!_isAttachedToLogicalTree) { if (_nameScope == null) { _nameScope = NameScope.GetNameScope(this) ?? ((Control)Parent)?._nameScope; } if (Name != null) { _nameScope?.Register(Name, this); } _isAttachedToLogicalTree = true; PerspexLocator.Current.GetService <IStyler>()?.ApplyStyles(this); AttachedToLogicalTree?.Invoke(this, e); } foreach (var child in LogicalChildren.OfType <Control>()) { child.OnAttachedToLogicalTree(e); } }
public static T RegisterInNameScope <T>(this T control, INameScope scope) where T : StyledElement { if (control.Name is null) { throw new ArgumentException("RegisterInNameScope must be called on a control with non-null name."); } scope.Register(control.Name, control); return(control); }
/// <summary> /// Registers the element to the proper name scope. /// </summary> private void RegisterWithNameScope() { if (_nameScope == null) { _nameScope = NameScope.GetNameScope(this) ?? ((Control)Parent)?._nameScope; } if (Name != null) { _nameScope?.Register(Name, this); } }
/// <summary> /// Registers each control with its name scope. /// </summary> /// <param name="control">The control.</param> /// <param name="nameScope">The name scope.</param> private void RegisterNames(IControl control, INameScope nameScope) { if (control.Name != null) { nameScope.Register(control.Name, control); } if (control.TemplatedParent == this) { foreach (IControl child in control.GetVisualChildren()) { RegisterNames(child, nameScope); } } }
/// <summary> /// Called when the control is added to a logical tree. /// </summary> /// <param name="e">The event args.</param> /// <remarks> /// It is vital that if you override this method you call the base implementation; /// failing to do so will cause numerous features to not work as expected. /// </remarks> protected virtual void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) { if (_nameScope == null) { _nameScope = NameScope.GetNameScope(this) ?? ((Control)Parent)?._nameScope; } if (Name != null) { _nameScope?.Register(Name, this); } _isAttachedToLogicalTree = true; PerspexLocator.Current.GetService <IStyler>()?.ApplyStyles(this); AttachedToLogicalTree?.Invoke(this, e); foreach (var child in LogicalChildren.OfType <Control>()) { child.OnAttachedToLogicalTree(e); } }
/// <summary> /// Sets the TemplatedParent property for a control created from the control template and /// applies the templates of nested templated controls. Also adds each control to its name /// scope if it has a name. /// </summary> /// <param name="control">The control.</param> /// <param name="nameScope">The name scope.</param> private void SetupTemplateControls(IControl control, INameScope nameScope) { // If control.TemplatedParent is null at this point, then the control is our templated // child so set its TemplatedParent and register it with its name scope. if (control.TemplatedParent == null) { control.SetValue(TemplatedParentProperty, this); if (control.Name != null) { nameScope.Register(control.Name, control); } } control.ApplyTemplate(); if (!(control is IPresenter && control.TemplatedParent == this)) { foreach (IControl child in control.GetVisualChildren()) { SetupTemplateControls(child, nameScope); } } }
public static T RegisterInNameScope <T>(this T control, INameScope scope) where T : StyledElement { scope.Register(control.Name, control); return(control); }