Control.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using Avalonia.Controls.Primitives;
  4. using Avalonia.Controls.Templates;
  5. using Avalonia.Input;
  6. using Avalonia.Interactivity;
  7. using Avalonia.Rendering;
  8. using Avalonia.Styling;
  9. using Avalonia.VisualTree;
  10. namespace Avalonia.Controls
  11. {
  12. /// <summary>
  13. /// Base class for Avalonia controls.
  14. /// </summary>
  15. /// <remarks>
  16. /// The control class extends <see cref="InputElement"/> and adds the following features:
  17. ///
  18. /// - A <see cref="Tag"/> property to allow user-defined data to be attached to the control.
  19. /// </remarks>
  20. public class Control : InputElement, IControl, INamed, ISupportInitialize, IVisualBrushInitialize, IRequiresTemplateInSetter
  21. {
  22. /// <summary>
  23. /// Defines the <see cref="FocusAdorner"/> property.
  24. /// </summary>
  25. public static readonly StyledProperty<ITemplate<IControl>> FocusAdornerProperty =
  26. AvaloniaProperty.Register<Control, ITemplate<IControl>>(nameof(FocusAdorner));
  27. /// <summary>
  28. /// Defines the <see cref="Tag"/> property.
  29. /// </summary>
  30. public static readonly StyledProperty<object> TagProperty =
  31. AvaloniaProperty.Register<Control, object>(nameof(Tag));
  32. /// <summary>
  33. /// Defines the <see cref="ContextMenu"/> property.
  34. /// </summary>
  35. public static readonly StyledProperty<ContextMenu> ContextMenuProperty =
  36. AvaloniaProperty.Register<Control, ContextMenu>(nameof(ContextMenu));
  37. /// <summary>
  38. /// Event raised when an element wishes to be scrolled into view.
  39. /// </summary>
  40. public static readonly RoutedEvent<RequestBringIntoViewEventArgs> RequestBringIntoViewEvent =
  41. RoutedEvent.Register<Control, RequestBringIntoViewEventArgs>("RequestBringIntoView", RoutingStrategies.Bubble);
  42. private DataTemplates _dataTemplates;
  43. private IControl _focusAdorner;
  44. /// <summary>
  45. /// Gets or sets the control's focus adorner.
  46. /// </summary>
  47. public ITemplate<IControl> FocusAdorner
  48. {
  49. get { return GetValue(FocusAdornerProperty); }
  50. set { SetValue(FocusAdornerProperty, value); }
  51. }
  52. /// <summary>
  53. /// Gets or sets the data templates for the control.
  54. /// </summary>
  55. /// <remarks>
  56. /// Each control may define data templates which are applied to the control itself and its
  57. /// children.
  58. /// </remarks>
  59. public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates());
  60. /// <summary>
  61. /// Gets or sets a context menu to the control.
  62. /// </summary>
  63. public ContextMenu ContextMenu
  64. {
  65. get { return GetValue(ContextMenuProperty); }
  66. set { SetValue(ContextMenuProperty, value); }
  67. }
  68. /// <summary>
  69. /// Gets or sets a user-defined object attached to the control.
  70. /// </summary>
  71. public object Tag
  72. {
  73. get { return GetValue(TagProperty); }
  74. set { SetValue(TagProperty, value); }
  75. }
  76. public new IControl Parent => (IControl)base.Parent;
  77. /// <inheritdoc/>
  78. bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
  79. /// <inheritdoc/>
  80. void IVisualBrushInitialize.EnsureInitialized()
  81. {
  82. if (VisualRoot == null)
  83. {
  84. if (!IsInitialized)
  85. {
  86. foreach (var i in this.GetSelfAndVisualDescendants())
  87. {
  88. var c = i as IControl;
  89. if (c?.IsInitialized == false)
  90. {
  91. var init = c as ISupportInitialize;
  92. if (init != null)
  93. {
  94. init.BeginInit();
  95. init.EndInit();
  96. }
  97. }
  98. }
  99. }
  100. if (!IsArrangeValid)
  101. {
  102. Measure(Size.Infinity);
  103. Arrange(new Rect(DesiredSize));
  104. }
  105. }
  106. }
  107. /// <summary>
  108. /// Gets the element that receives the focus adorner.
  109. /// </summary>
  110. /// <returns>The control that receives the focus adorner.</returns>
  111. protected virtual IControl GetTemplateFocusTarget()
  112. {
  113. return this;
  114. }
  115. /// <inheritdoc/>
  116. protected sealed override void OnAttachedToVisualTreeCore(VisualTreeAttachmentEventArgs e)
  117. {
  118. base.OnAttachedToVisualTreeCore(e);
  119. InitializeIfNeeded();
  120. }
  121. /// <inheritdoc/>
  122. protected sealed override void OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e)
  123. {
  124. base.OnDetachedFromVisualTreeCore(e);
  125. }
  126. /// <inheritdoc/>
  127. protected override void OnGotFocus(GotFocusEventArgs e)
  128. {
  129. base.OnGotFocus(e);
  130. if (IsFocused &&
  131. (e.NavigationMethod == NavigationMethod.Tab ||
  132. e.NavigationMethod == NavigationMethod.Directional))
  133. {
  134. var adornerLayer = AdornerLayer.GetAdornerLayer(this);
  135. if (adornerLayer != null)
  136. {
  137. if (_focusAdorner == null)
  138. {
  139. var template = GetValue(FocusAdornerProperty);
  140. if (template != null)
  141. {
  142. _focusAdorner = template.Build();
  143. }
  144. }
  145. if (_focusAdorner != null)
  146. {
  147. var target = (Visual)GetTemplateFocusTarget();
  148. if (target != null)
  149. {
  150. AdornerLayer.SetAdornedElement((Visual)_focusAdorner, target);
  151. adornerLayer.Children.Add(_focusAdorner);
  152. }
  153. }
  154. }
  155. }
  156. }
  157. /// <inheritdoc/>
  158. protected override void OnLostFocus(RoutedEventArgs e)
  159. {
  160. base.OnLostFocus(e);
  161. if (_focusAdorner != null)
  162. {
  163. var adornerLayer = (IPanel)_focusAdorner.Parent;
  164. adornerLayer.Children.Remove(_focusAdorner);
  165. _focusAdorner = null;
  166. }
  167. }
  168. }
  169. }