| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- // Copyright (c) The Avalonia Project. All rights reserved.
- // Licensed under the MIT license. See licence.md file in the project root for full license information.
- using Avalonia.Controls.Primitives;
- using Avalonia.Controls.Templates;
- using Avalonia.Input;
- using Avalonia.Interactivity;
- using Avalonia.Rendering;
- using Avalonia.Styling;
- using Avalonia.VisualTree;
- namespace Avalonia.Controls
- {
- /// <summary>
- /// Base class for Avalonia controls.
- /// </summary>
- /// <remarks>
- /// The control class extends <see cref="InputElement"/> and adds the following features:
- ///
- /// - A <see cref="Tag"/> property to allow user-defined data to be attached to the control.
- /// </remarks>
- public class Control : InputElement, IControl, INamed, ISupportInitialize, IVisualBrushInitialize, IRequiresTemplateInSetter
- {
- /// <summary>
- /// Defines the <see cref="FocusAdorner"/> property.
- /// </summary>
- public static readonly StyledProperty<ITemplate<IControl>> FocusAdornerProperty =
- AvaloniaProperty.Register<Control, ITemplate<IControl>>(nameof(FocusAdorner));
- /// <summary>
- /// Defines the <see cref="Tag"/> property.
- /// </summary>
- public static readonly StyledProperty<object> TagProperty =
- AvaloniaProperty.Register<Control, object>(nameof(Tag));
-
- /// <summary>
- /// Defines the <see cref="ContextMenu"/> property.
- /// </summary>
- public static readonly StyledProperty<ContextMenu> ContextMenuProperty =
- AvaloniaProperty.Register<Control, ContextMenu>(nameof(ContextMenu));
- /// <summary>
- /// Event raised when an element wishes to be scrolled into view.
- /// </summary>
- public static readonly RoutedEvent<RequestBringIntoViewEventArgs> RequestBringIntoViewEvent =
- RoutedEvent.Register<Control, RequestBringIntoViewEventArgs>("RequestBringIntoView", RoutingStrategies.Bubble);
- private DataTemplates _dataTemplates;
- private IControl _focusAdorner;
- /// <summary>
- /// Gets or sets the control's focus adorner.
- /// </summary>
- public ITemplate<IControl> FocusAdorner
- {
- get { return GetValue(FocusAdornerProperty); }
- set { SetValue(FocusAdornerProperty, value); }
- }
- /// <summary>
- /// Gets or sets the data templates for the control.
- /// </summary>
- /// <remarks>
- /// Each control may define data templates which are applied to the control itself and its
- /// children.
- /// </remarks>
- public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates());
- /// <summary>
- /// Gets or sets a context menu to the control.
- /// </summary>
- public ContextMenu ContextMenu
- {
- get { return GetValue(ContextMenuProperty); }
- set { SetValue(ContextMenuProperty, value); }
- }
- /// <summary>
- /// Gets or sets a user-defined object attached to the control.
- /// </summary>
- public object Tag
- {
- get { return GetValue(TagProperty); }
- set { SetValue(TagProperty, value); }
- }
- public new IControl Parent => (IControl)base.Parent;
- /// <inheritdoc/>
- bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
- /// <inheritdoc/>
- void IVisualBrushInitialize.EnsureInitialized()
- {
- if (VisualRoot == null)
- {
- if (!IsInitialized)
- {
- foreach (var i in this.GetSelfAndVisualDescendants())
- {
- var c = i as IControl;
- if (c?.IsInitialized == false)
- {
- var init = c as ISupportInitialize;
- if (init != null)
- {
- init.BeginInit();
- init.EndInit();
- }
- }
- }
- }
- if (!IsArrangeValid)
- {
- Measure(Size.Infinity);
- Arrange(new Rect(DesiredSize));
- }
- }
- }
- /// <summary>
- /// Gets the element that receives the focus adorner.
- /// </summary>
- /// <returns>The control that receives the focus adorner.</returns>
- protected virtual IControl GetTemplateFocusTarget()
- {
- return this;
- }
- /// <inheritdoc/>
- protected sealed override void OnAttachedToVisualTreeCore(VisualTreeAttachmentEventArgs e)
- {
- base.OnAttachedToVisualTreeCore(e);
- InitializeIfNeeded();
- }
- /// <inheritdoc/>
- protected sealed override void OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e)
- {
- base.OnDetachedFromVisualTreeCore(e);
- }
- /// <inheritdoc/>
- protected override void OnGotFocus(GotFocusEventArgs e)
- {
- base.OnGotFocus(e);
- if (IsFocused &&
- (e.NavigationMethod == NavigationMethod.Tab ||
- e.NavigationMethod == NavigationMethod.Directional))
- {
- var adornerLayer = AdornerLayer.GetAdornerLayer(this);
- if (adornerLayer != null)
- {
- if (_focusAdorner == null)
- {
- var template = GetValue(FocusAdornerProperty);
- if (template != null)
- {
- _focusAdorner = template.Build();
- }
- }
- if (_focusAdorner != null)
- {
- var target = (Visual)GetTemplateFocusTarget();
- if (target != null)
- {
- AdornerLayer.SetAdornedElement((Visual)_focusAdorner, target);
- adornerLayer.Children.Add(_focusAdorner);
- }
- }
- }
- }
- }
- /// <inheritdoc/>
- protected override void OnLostFocus(RoutedEventArgs e)
- {
- base.OnLostFocus(e);
- if (_focusAdorner != null)
- {
- var adornerLayer = (IPanel)_focusAdorner.Parent;
- adornerLayer.Children.Remove(_focusAdorner);
- _focusAdorner = null;
- }
- }
- }
- }
|