// Copyright (c) The Perspex Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using Perspex.Animation; using Perspex.Controls.Generators; using Perspex.Controls.Primitives; using Perspex.Controls.Templates; namespace Perspex.Controls { /// /// A tab control that displays a tab strip along with the content of the selected tab. /// public class TabControl : SelectingItemsControl { /// /// Defines the property. /// public static readonly StyledProperty TransitionProperty = Perspex.Controls.Carousel.TransitionProperty.AddOwner(); /// /// Defines an that selects the content of a . /// public static readonly IMemberSelector ContentSelector = new FuncMemberSelector(SelectContent); /// /// Defines an that selects the header of a . /// public static readonly IMemberSelector HeaderSelector = new FuncMemberSelector(SelectHeader); /// /// Defines the property. /// public static readonly StyledProperty TabStripPlacementProperty = PerspexProperty.Register(nameof(TabStripPlacement), defaultValue: Dock.Top); /// /// Initializes static members of the class. /// static TabControl() { SelectionModeProperty.OverrideDefaultValue(SelectionMode.AlwaysSelected); FocusableProperty.OverrideDefaultValue(false); AffectsMeasure(TabStripPlacementProperty); } /// /// Gets the pages portion of the 's template. /// public IControl Pages { get; private set; } /// /// Gets the tab strip portion of the 's template. /// public IControl TabStrip { get; private set; } /// /// Gets or sets the transition to use when switching tabs. /// public IPageTransition Transition { get { return GetValue(TransitionProperty); } set { SetValue(TransitionProperty, value); } } /// /// Gets or sets the tabstrip placement of the tabcontrol. /// public Dock TabStripPlacement { get { return GetValue(TabStripPlacementProperty); } set { SetValue(TabStripPlacementProperty, value); } } protected override IItemContainerGenerator CreateItemContainerGenerator() { // TabControl doesn't actually create items - instead its TabStrip and Carousel // children create the items. However we want it to be a SelectingItemsControl // so that it has the Items/SelectedItem etc properties. In this case, we can // return a null ItemContainerGenerator to disable the creation of item containers. return null; } protected override void OnTemplateApplied(TemplateAppliedEventArgs e) { base.OnTemplateApplied(e); TabStrip = e.NameScope.Find("PART_TabStrip"); Pages = e.NameScope.Find("PART_Content"); } /// /// Selects the content of a tab item. /// /// The tab item. /// The content. private static object SelectContent(object o) { var content = o as IContentControl; if (content != null) { return content.Content; } else { return o; } } /// /// Selects the header of a tab item. /// /// The tab item. /// The content. private static object SelectHeader(object o) { var headered = o as IHeadered; var control = o as IControl; if (headered != null) { return headered.Header ?? string.Empty; } else if (control != null) { // Non-headered control items should result in TabStripItems with empty content. // If a TabStrip is created with non IHeadered controls as its items, don't try to // display the control in the TabStripItem: the content portion will also try to // display this control, resulting in dual-parentage breakage. return string.Empty; } else { return o; } } } }