using System.ComponentModel; using System.Linq; using Avalonia.Collections; using Avalonia.Controls.Generators; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Input; using Avalonia.Layout; using Avalonia.LogicalTree; using Avalonia.VisualTree; namespace Avalonia.Controls { /// /// A tab control that displays a tab strip along with the content of the selected tab. /// public class TabControl : SelectingItemsControl, IContentPresenterHost { /// /// Defines the property. /// public static readonly StyledProperty TabStripPlacementProperty = AvaloniaProperty.Register(nameof(TabStripPlacement), defaultValue: Dock.Top); /// /// Defines the property. /// public static readonly StyledProperty HorizontalContentAlignmentProperty = ContentControl.HorizontalContentAlignmentProperty.AddOwner(); /// /// Defines the property. /// public static readonly StyledProperty VerticalContentAlignmentProperty = ContentControl.VerticalContentAlignmentProperty.AddOwner(); /// /// Defines the property. /// public static readonly StyledProperty ContentTemplateProperty = ContentControl.ContentTemplateProperty.AddOwner(); /// /// The selected content property /// public static readonly StyledProperty SelectedContentProperty = AvaloniaProperty.Register(nameof(SelectedContent)); /// /// The selected content template property /// public static readonly StyledProperty SelectedContentTemplateProperty = AvaloniaProperty.Register(nameof(SelectedContentTemplate)); /// /// The default value for the property. /// private static readonly FuncTemplate DefaultPanel = new FuncTemplate(() => new WrapPanel()); /// /// Initializes static members of the class. /// static TabControl() { SelectionModeProperty.OverrideDefaultValue(SelectionMode.AlwaysSelected); ItemsPanelProperty.OverrideDefaultValue(DefaultPanel); AffectsMeasure(TabStripPlacementProperty); SelectedItemProperty.Changed.AddClassHandler((x, e) => x.UpdateSelectedContent()); } /// /// Gets or sets the horizontal alignment of the content within the control. /// public HorizontalAlignment HorizontalContentAlignment { get { return GetValue(HorizontalContentAlignmentProperty); } set { SetValue(HorizontalContentAlignmentProperty, value); } } /// /// Gets or sets the vertical alignment of the content within the control. /// public VerticalAlignment VerticalContentAlignment { get { return GetValue(VerticalContentAlignmentProperty); } set { SetValue(VerticalContentAlignmentProperty, value); } } /// /// Gets or sets the tabstrip placement of the TabControl. /// public Dock TabStripPlacement { get { return GetValue(TabStripPlacementProperty); } set { SetValue(TabStripPlacementProperty, value); } } /// /// Gets or sets the default data template used to display the content of the selected tab. /// public IDataTemplate ContentTemplate { get { return GetValue(ContentTemplateProperty); } set { SetValue(ContentTemplateProperty, value); } } /// /// Gets or sets the content of the selected tab. /// /// /// The content of the selected tab. /// public object SelectedContent { get { return GetValue(SelectedContentProperty); } internal set { SetValue(SelectedContentProperty, value); } } /// /// Gets or sets the content template for the selected tab. /// /// /// The content template of the selected tab. /// public IDataTemplate SelectedContentTemplate { get { return GetValue(SelectedContentTemplateProperty); } internal set { SetValue(SelectedContentTemplateProperty, value); } } internal ItemsPresenter ItemsPresenterPart { get; private set; } internal IContentPresenter ContentPart { get; private set; } /// IAvaloniaList IContentPresenterHost.LogicalChildren => LogicalChildren; /// bool IContentPresenterHost.RegisterContentPresenter(IContentPresenter presenter) { return RegisterContentPresenter(presenter); } protected override void OnContainersMaterialized(ItemContainerEventArgs e) { base.OnContainersMaterialized(e); UpdateSelectedContent(); } protected override void OnContainersRecycled(ItemContainerEventArgs e) { base.OnContainersRecycled(e); UpdateSelectedContent(); } private void UpdateSelectedContent() { if (SelectedIndex == -1) { SelectedContent = SelectedContentTemplate = null; } else { var container = SelectedItem as IContentControl ?? ItemContainerGenerator.ContainerFromIndex(SelectedIndex) as IContentControl; SelectedContentTemplate = container?.ContentTemplate; SelectedContent = container?.Content; } } /// /// Called when an is registered with the control. /// /// The presenter. protected virtual bool RegisterContentPresenter(IContentPresenter presenter) { if (presenter.Name == "PART_SelectedContentHost") { ContentPart = presenter; return true; } return false; } protected override IItemContainerGenerator CreateItemContainerGenerator() { return new TabItemContainerGenerator(this); } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { ItemsPresenterPart = e.NameScope.Get("PART_ItemsPresenter"); } /// protected override void OnGotFocus(GotFocusEventArgs e) { base.OnGotFocus(e); if (e.NavigationMethod == NavigationMethod.Directional) { e.Handled = UpdateSelectionFromEventSource(e.Source); } } /// protected override void OnPointerPressed(PointerPressedEventArgs e) { base.OnPointerPressed(e); if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && e.Pointer.Type == PointerType.Mouse) { e.Handled = UpdateSelectionFromEventSource(e.Source); } } protected override void OnPointerReleased(PointerReleasedEventArgs e) { if (e.InitialPressMouseButton == MouseButton.Left && e.Pointer.Type != PointerType.Mouse) { var container = GetContainerFromEventSource(e.Source); if (container != null && container.GetVisualsAt(e.GetPosition(container)) .Any(c => container == c || container.IsVisualAncestorOf(c))) { e.Handled = UpdateSelectionFromEventSource(e.Source); } } } } }