TabControl.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / Controls / TabControl.cs / 1 / TabControl.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System.ComponentModel; 
using System.Collections; 
using System.Collections.Specialized;
using System.Diagnostics; 
using System.Globalization;
using System.Windows.Threading;
using System.Windows.Data;
using System.Windows.Input; 
using System.Windows;
using System.Windows.Automation.Peers; 
using System.Windows.Media; 
using System.Windows.Controls.Primitives;
using System.Windows.Markup; 
using MS.Utility;

using System;
 
namespace System.Windows.Controls
{ 
    ///  
    ///     TabControl allows a developer to arrange visual content in a compacted and organized form.
    /// The real-world analog of the control might be a tabbed notebook, 
    /// in which visual content is displayed in discreet pages which are accessed
    /// by selecting the appropriate tab.  Each tab/page is encapsulated by a TabItem,
    /// the generated item of TabControl.
    /// A TabItem has a Header property which corresponds to the content in the tab button 
    /// and a Content property which corresponds to the content in the tab page.
    /// This control is useful for minimizing screen space usage while allowing an application to expose a large amount of data. 
    /// The user navigates through TabItems by clicking on a tab button using the mouse or by using the keyboard. 
    /// 
    [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(TabItem))] 
    [TemplatePart(Name = "PART_SelectedContentHost", Type = typeof(ContentPresenter))]
    public class TabControl : Selector
    {
        #region Constructors 

        static TabControl() 
        { 
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TabControl), new FrameworkPropertyMetadata(typeof(TabControl)));
            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(TabControl)); 
            IsTabStopProperty.OverrideMetadata(typeof(TabControl), new FrameworkPropertyMetadata(MS.Internal.KnownBoxes.BooleanBoxes.FalseBox));
            KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(TabControl), new FrameworkPropertyMetadata(KeyboardNavigationMode.Contained));
        }
 
        /// 
        ///     Default TabControl constructor 
        ///  
        /// 
        ///     Automatic determination of current Dispatcher. Use alternative constructor 
        ///     that accepts a Dispatcher for best performance.
        /// 
        public TabControl() : base()
        { 
        }
 
        #endregion 

        #region Properties 

        /// 
        ///     The DependencyProperty for the TabStripPlacement property.
        ///     Flags:              None 
        ///     Default Value:      Dock.Top
        ///  
        public static readonly DependencyProperty TabStripPlacementProperty = 
                    DependencyProperty.Register(
                            "TabStripPlacement", 
                            typeof(Dock),
                            typeof(TabControl),
                            new FrameworkPropertyMetadata(
                                    Dock.Top, 
                                    new PropertyChangedCallback(OnTabStripPlacementPropertyChanged)),
                            new ValidateValueCallback(DockPanel.IsValidDock)); 
 
        // When TabControl TabStripPlacement is changing we need to invalidate its TabItem TabStripPlacement
        private static void OnTabStripPlacementPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            TabControl tc = (TabControl)d;
            ItemCollection tabItemCollection = tc.Items;
            for (int i = 0; i < tabItemCollection.Count; i++) 
            {
                TabItem ti = tc.ItemContainerGenerator.ContainerFromIndex(i) as TabItem; 
                if (ti != null) 
                    ti.CoerceValue(TabItem.TabStripPlacementProperty);
            } 
        }

        /// 
        ///     TabStripPlacement specify how tab headers align relatively to content 
        /// 
        [Bindable(true), Category("Behavior")] 
        public Dock TabStripPlacement 
        {
            get 
            {
                return (Dock)GetValue(TabStripPlacementProperty);
            }
            set 
            {
                SetValue(TabStripPlacementProperty, value); 
            } 
        }
 
        private static readonly DependencyPropertyKey SelectedContentPropertyKey = DependencyProperty.RegisterReadOnly("SelectedContent", typeof(object), typeof(TabControl), new FrameworkPropertyMetadata((object)null));

        /// 
        ///     The DependencyProperty for the SelectedContent property. 
        ///     Flags:              None
        ///     Default Value:      null 
        ///  
        public static readonly DependencyProperty SelectedContentProperty = SelectedContentPropertyKey.DependencyProperty;
 
        /// 
        ///     SelectedContent is the Content of current SelectedItem.
        /// This property is updated whenever the selection is changed.
        /// It always keeps a reference to active TabItem.Content 
        /// Used for aliasing in default TabControl Style
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public object SelectedContent
        { 
            get
            {
                return GetValue(SelectedContentProperty);
            } 
            internal set
            { 
                SetValue(SelectedContentPropertyKey, value); 
            }
        } 

        private static readonly DependencyPropertyKey SelectedContentTemplatePropertyKey = DependencyProperty.RegisterReadOnly("SelectedContentTemplate", typeof(DataTemplate), typeof(TabControl), new FrameworkPropertyMetadata((DataTemplate)null));

        ///  
        ///     The DependencyProperty for the SelectedContentTemplate property.
        ///     Flags:              None 
        ///     Default Value:      null 
        /// 
        public static readonly DependencyProperty SelectedContentTemplateProperty = SelectedContentTemplatePropertyKey.DependencyProperty; 

        /// 
        ///     SelectedContentTemplate is the ContentTemplate of current SelectedItem.
        /// This property is updated whenever the selection is changed. 
        /// It always keeps a reference to active TabItem.ContentTemplate
        /// It is used for aliasing in default TabControl Style 
        ///  
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public DataTemplate SelectedContentTemplate
        {
            get
            { 
                return (DataTemplate)GetValue(SelectedContentTemplateProperty);
            } 
            internal set 
            {
                SetValue(SelectedContentTemplatePropertyKey, value); 
            }
        }

        private static readonly DependencyPropertyKey SelectedContentTemplateSelectorPropertyKey = DependencyProperty.RegisterReadOnly("SelectedContentTemplateSelector", typeof(DataTemplateSelector), typeof(TabControl), new FrameworkPropertyMetadata((DataTemplateSelector)null)); 

        ///  
        ///     The DependencyProperty for the SelectedContentTemplateSelector property. 
        ///     Flags:              None
        ///     Default Value:      null 
        /// 
        public static readonly DependencyProperty SelectedContentTemplateSelectorProperty = SelectedContentTemplateSelectorPropertyKey.DependencyProperty;

        ///  
        ///     SelectedContentTemplateSelector allows the app writer to provide custom style selection logic.
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public DataTemplateSelector SelectedContentTemplateSelector
        { 
            get
            {
                return (DataTemplateSelector)GetValue(SelectedContentTemplateSelectorProperty);
            } 
            internal set
            { 
                SetValue(SelectedContentTemplateSelectorPropertyKey, value); 
            }
        } 

        private static readonly DependencyPropertyKey SelectedContentStringFormatPropertyKey =
                DependencyProperty.RegisterReadOnly("SelectedContentStringFormat",
                        typeof(String), 
                        typeof(TabControl),
                        new FrameworkPropertyMetadata((String)null)); 
 
        /// 
        ///     The DependencyProperty for the SelectedContentStringFormat property. 
        ///     Flags:              None
        ///     Default Value:      null
        /// 
        public static readonly DependencyProperty SelectedContentStringFormatProperty = 
                SelectedContentStringFormatPropertyKey.DependencyProperty;
 
 
        /// 
        ///     ContentStringFormat is the format used to display the content of 
        ///     the control as a string.  This arises only when no template is
        ///     available.
        /// 
        public String SelectedContentStringFormat 
        {
            get { return (String) GetValue(SelectedContentStringFormatProperty); } 
            internal set { SetValue(SelectedContentStringFormatPropertyKey, value); } 
        }
 

        /// 
        ///     The DependencyProperty for the ContentTemplate property.
        ///     Flags:              None 
        ///     Default Value:      null
        ///  
        public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.Register("ContentTemplate", typeof(DataTemplate), typeof(TabControl), new FrameworkPropertyMetadata((DataTemplate)null)); 

        ///  
        /// ContentTemplate is the ContentTemplate to apply to TabItems
        /// that do not have the ContentTemplate or ContentTemplateSelector properties
        /// defined
        ///  
        /// 
        public DataTemplate ContentTemplate 
        { 
            get
            { 
                return (DataTemplate)GetValue(ContentTemplateProperty);
            }
            set
            { 
                SetValue(ContentTemplateProperty, value);
            } 
        } 

        ///  
        ///     The DependencyProperty for the ContentTemplateSelector property.
        ///     Flags:              None
        ///     Default Value:      null
        ///  
        public static readonly DependencyProperty ContentTemplateSelectorProperty = DependencyProperty.Register("ContentTemplateSelector", typeof(DataTemplateSelector), typeof(TabControl), new FrameworkPropertyMetadata((DataTemplateSelector)null));
 
        ///  
        ///     ContentTemplateSelector allows the app writer to provide custom style selection logic.
        ///  
        public DataTemplateSelector ContentTemplateSelector
        {
            get
            { 
                return (DataTemplateSelector)GetValue(ContentTemplateSelectorProperty);
            } 
            set 
            {
                SetValue(ContentTemplateSelectorProperty, value); 
            }
        }

        ///  
        ///     The DependencyProperty for the ContentStringFormat property.
        ///     Flags:              None 
        ///     Default Value:      null 
        /// 
        public static readonly DependencyProperty ContentStringFormatProperty = 
                DependencyProperty.Register(
                        "ContentStringFormat",
                        typeof(String),
                        typeof(TabControl), 
                        new FrameworkPropertyMetadata((String) null));
 
 
        /// 
        ///     ContentStringFormat is the format used to display the content of 
        ///     the control as a string.  This arises only when no template is
        ///     available.
        /// 
        public String ContentStringFormat 
        {
            get { return (String) GetValue(ContentStringFormatProperty); } 
            set { SetValue(ContentStringFormatProperty, value); } 
        }
 
        #endregion

        #region Overrided Methods
 
        /// 
        /// Creates AutomationPeer () 
        ///  
        protected override AutomationPeer OnCreateAutomationPeer()
        { 
            return new TabControlAutomationPeer(this);
        }

        ///  
        ///     This virtual method in called when IsInitialized is set to true and it raises an Initialized event
        ///  
        protected override void OnInitialized(EventArgs e) 
        {
            base.OnInitialized(e); 
            CanSelectMultiple = false;
            ItemContainerGenerator.StatusChanged += new EventHandler(OnGeneratorStatusChanged);
        }
        ///  
        /// Called when the Template's tree has been generated. When Template gets expanded we ensure that SelectedContent is in [....]
        ///  
        public override void OnApplyTemplate() 
        {
            base.OnApplyTemplate(); 
            UpdateSelectedContent();
        }

        ///  
        /// A virtual function that is called when the selection is changed. Default behavior
        /// is to raise a SelectionChangedEvent 
        ///  
        /// The inputs for this event. Can be raised (default behavior) or processed
        ///   in some other way. 
        protected override void OnSelectionChanged(SelectionChangedEventArgs e)
        {
            base.OnSelectionChanged(e);
            if (IsKeyboardFocusWithin) 
            {
                // If keyboard focus is within the control, make sure it is going to the correct place 
                TabItem item = GetSelectedTabItem(); 
                if (item != null)
                { 
                    item.SetFocus();
                }
            }
            UpdateSelectedContent(); 

            if (    AutomationPeer.ListenerExists(AutomationEvents.SelectionPatternOnInvalidated) 
                ||  AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementSelected) 
                ||  AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementAddedToSelection)
                ||  AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementRemovedFromSelection)   ) 
            {
                TabControlAutomationPeer peer = UIElementAutomationPeer.CreatePeerForElement(this) as TabControlAutomationPeer;
                if (peer != null)
                    peer.RaiseSelectionEvents(e); 
            }
        } 
 
        /// 
        /// Updates the current selection when Items has changed 
        /// 
        /// Information about what has changed
        protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
        { 
            base.OnItemsChanged(e);
            if (e.Action == NotifyCollectionChangedAction.Remove && SelectedIndex == -1) 
            { 
                // If we remove the selected item we should select the previous item
                int startIndex = e.OldStartingIndex + 1; 
                if (startIndex > Items.Count)
                    startIndex = 0;
                TabItem nextTabItem = FindNextTabItem(startIndex, -1);
                if (nextTabItem != null) 
                    nextTabItem.IsSelected = true;
            } 
        } 

        ///  
        /// This is the method that responds to the KeyDown event.
        /// 
        /// 
        protected override void OnKeyDown(KeyEventArgs e) 
        {
            TabItem nextTabItem = null; 
 
            // Handle [Ctrl][Shift]Tab, Home and End cases
            // We have special handling here because if focus is inside the TabItem content we cannot 
            // cycle through TabItem because the content is not part of the TabItem visual tree

            int direction = 0;
            int startIndex = -1; 
            switch (e.Key)
            { 
                case Key.Tab: 
                    if ((e.KeyboardDevice.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                    { 
                        startIndex = ItemContainerGenerator.IndexFromContainer(ItemContainerGenerator.ContainerFromItem(SelectedItem));
                        if ((e.KeyboardDevice.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
                            direction = -1;
                        else 
                            direction = 1;
                    } 
                    break; 
                case Key.Home:
                    direction = 1; 
                    startIndex = -1;
                    break;
                case Key.End:
                    direction = -1; 
                    startIndex = Items.Count;
                    break; 
            } 

            nextTabItem = FindNextTabItem(startIndex, direction); 

            if (nextTabItem != null && nextTabItem != SelectedItem)
            {
                e.Handled = nextTabItem.SetFocus(); 
            }
 
            if (!e.Handled) 
                base.OnKeyDown(e);
        } 

        private TabItem FindNextTabItem(int startIndex, int direction)
        {
            TabItem nextTabItem = null; 
            if (direction != 0)
            { 
                int index = startIndex; 
                for (int i = 0; i < Items.Count; i++)
                { 
                    index += direction;
                    if (index >= Items.Count)
                        index = 0;
                    else if (index < 0) 
                        index = Items.Count - 1;
 
                    TabItem tabItem = ItemContainerGenerator.ContainerFromIndex(index) as TabItem; 
                    if (tabItem != null && tabItem.IsEnabled && tabItem.Visibility == Visibility.Visible)
                    { 
                        nextTabItem = tabItem;
                        break;
                    }
                } 
            }
            return nextTabItem; 
        } 

        ///  
        /// Return true if the item is (or is eligible to be) its own ItemUI
        /// 
        protected override bool IsItemItsOwnContainerOverride(object item)
        { 
            return (item is TabItem);
        } 
 
        ///  Create or identify the element used to display the given item. 
        protected override DependencyObject GetContainerForItemOverride() 
        {
            return new TabItem();
        }
 
        #endregion
 
        #region private helpers 

        internal ContentPresenter SelectedContentPresenter 
        {
            get
            {
                return GetTemplateChild(SelectedContentHostTemplateName) as ContentPresenter; 
            }
        } 
 
        private void OnGeneratorStatusChanged(object sender, EventArgs e)
        { 
            if (ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
            {
                if (HasItems && _selectedItems.Count == 0)
                { 
                    SelectedIndex = 0;
                } 
 
                UpdateSelectedContent();
            } 
        }

        private TabItem GetSelectedTabItem()
        { 
            object selectedItem = SelectedItem;
            if (selectedItem != null) 
            { 
                // Check if the selected item is a TabItem
                TabItem tabItem = selectedItem as TabItem; 
                if (tabItem == null)
                {
                    // It is a data item, get its TabItem container
                    tabItem = ItemContainerGenerator.ContainerFromIndex(SelectedIndex) as TabItem; 
                }
 
                return tabItem; 
            }
 
            return null;
        }

        // When selection is changed we need to copy the active TabItem content in SelectedContent property 
        // SelectedContent is aliased in the TabControl style
        private void UpdateSelectedContent() 
        { 
            if (SelectedIndex < 0)
            { 
                SelectedContent = null;
                SelectedContentTemplate = null;
                SelectedContentTemplateSelector = null;
                SelectedContentStringFormat = null; 
                return;
            } 
 
            TabItem tabItem = GetSelectedTabItem();
            if (tabItem != null) 
            {
                FrameworkElement visualParent = VisualTreeHelper.GetParent(tabItem) as FrameworkElement;

                if (visualParent != null) 
                {
                    KeyboardNavigation.SetTabOnceActiveElement(visualParent, tabItem); 
                    KeyboardNavigation.SetTabOnceActiveElement(this, visualParent); 
                }
 
                SelectedContent = tabItem.Content;
                ContentPresenter scp = SelectedContentPresenter;
                if (scp != null)
                { 
                    scp.HorizontalAlignment = tabItem.HorizontalContentAlignment;
                    scp.VerticalAlignment = tabItem.VerticalContentAlignment; 
                } 

                // Use tabItem's template or selector if specified, otherwise use TabControl's 
                if (tabItem.ContentTemplate != null || tabItem.ContentTemplateSelector != null || tabItem.ContentStringFormat != null)
                {
                    SelectedContentTemplate = tabItem.ContentTemplate;
                    SelectedContentTemplateSelector = tabItem.ContentTemplateSelector; 
                    SelectedContentStringFormat = tabItem.ContentStringFormat;
                } 
                else 
                {
                    SelectedContentTemplate = ContentTemplate; 
                    SelectedContentTemplateSelector = ContentTemplateSelector;
                    SelectedContentStringFormat = ContentStringFormat;
                }
             } 
        }
 
        #endregion private helpers 

        #region private data 

        // Part name used in the style. The class TemplatePartAttribute should use the same name
        private const string SelectedContentHostTemplateName = "PART_SelectedContentHost";
 
        #endregion
 
        #region DTypeThemeStyleKey 

        // Returns the DependencyObjectType for the registered ThemeStyleKey's default 
        // value. Controls will override this method to return approriate types.
        internal override DependencyObjectType DTypeThemeStyleKey
        {
            get { return _dType; } 
        }
 
        private static DependencyObjectType _dType; 

        #endregion DTypeThemeStyleKey 
    }
}


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System.ComponentModel; 
using System.Collections; 
using System.Collections.Specialized;
using System.Diagnostics; 
using System.Globalization;
using System.Windows.Threading;
using System.Windows.Data;
using System.Windows.Input; 
using System.Windows;
using System.Windows.Automation.Peers; 
using System.Windows.Media; 
using System.Windows.Controls.Primitives;
using System.Windows.Markup; 
using MS.Utility;

using System;
 
namespace System.Windows.Controls
{ 
    ///  
    ///     TabControl allows a developer to arrange visual content in a compacted and organized form.
    /// The real-world analog of the control might be a tabbed notebook, 
    /// in which visual content is displayed in discreet pages which are accessed
    /// by selecting the appropriate tab.  Each tab/page is encapsulated by a TabItem,
    /// the generated item of TabControl.
    /// A TabItem has a Header property which corresponds to the content in the tab button 
    /// and a Content property which corresponds to the content in the tab page.
    /// This control is useful for minimizing screen space usage while allowing an application to expose a large amount of data. 
    /// The user navigates through TabItems by clicking on a tab button using the mouse or by using the keyboard. 
    /// 
    [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(TabItem))] 
    [TemplatePart(Name = "PART_SelectedContentHost", Type = typeof(ContentPresenter))]
    public class TabControl : Selector
    {
        #region Constructors 

        static TabControl() 
        { 
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TabControl), new FrameworkPropertyMetadata(typeof(TabControl)));
            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(TabControl)); 
            IsTabStopProperty.OverrideMetadata(typeof(TabControl), new FrameworkPropertyMetadata(MS.Internal.KnownBoxes.BooleanBoxes.FalseBox));
            KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(TabControl), new FrameworkPropertyMetadata(KeyboardNavigationMode.Contained));
        }
 
        /// 
        ///     Default TabControl constructor 
        ///  
        /// 
        ///     Automatic determination of current Dispatcher. Use alternative constructor 
        ///     that accepts a Dispatcher for best performance.
        /// 
        public TabControl() : base()
        { 
        }
 
        #endregion 

        #region Properties 

        /// 
        ///     The DependencyProperty for the TabStripPlacement property.
        ///     Flags:              None 
        ///     Default Value:      Dock.Top
        ///  
        public static readonly DependencyProperty TabStripPlacementProperty = 
                    DependencyProperty.Register(
                            "TabStripPlacement", 
                            typeof(Dock),
                            typeof(TabControl),
                            new FrameworkPropertyMetadata(
                                    Dock.Top, 
                                    new PropertyChangedCallback(OnTabStripPlacementPropertyChanged)),
                            new ValidateValueCallback(DockPanel.IsValidDock)); 
 
        // When TabControl TabStripPlacement is changing we need to invalidate its TabItem TabStripPlacement
        private static void OnTabStripPlacementPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            TabControl tc = (TabControl)d;
            ItemCollection tabItemCollection = tc.Items;
            for (int i = 0; i < tabItemCollection.Count; i++) 
            {
                TabItem ti = tc.ItemContainerGenerator.ContainerFromIndex(i) as TabItem; 
                if (ti != null) 
                    ti.CoerceValue(TabItem.TabStripPlacementProperty);
            } 
        }

        /// 
        ///     TabStripPlacement specify how tab headers align relatively to content 
        /// 
        [Bindable(true), Category("Behavior")] 
        public Dock TabStripPlacement 
        {
            get 
            {
                return (Dock)GetValue(TabStripPlacementProperty);
            }
            set 
            {
                SetValue(TabStripPlacementProperty, value); 
            } 
        }
 
        private static readonly DependencyPropertyKey SelectedContentPropertyKey = DependencyProperty.RegisterReadOnly("SelectedContent", typeof(object), typeof(TabControl), new FrameworkPropertyMetadata((object)null));

        /// 
        ///     The DependencyProperty for the SelectedContent property. 
        ///     Flags:              None
        ///     Default Value:      null 
        ///  
        public static readonly DependencyProperty SelectedContentProperty = SelectedContentPropertyKey.DependencyProperty;
 
        /// 
        ///     SelectedContent is the Content of current SelectedItem.
        /// This property is updated whenever the selection is changed.
        /// It always keeps a reference to active TabItem.Content 
        /// Used for aliasing in default TabControl Style
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public object SelectedContent
        { 
            get
            {
                return GetValue(SelectedContentProperty);
            } 
            internal set
            { 
                SetValue(SelectedContentPropertyKey, value); 
            }
        } 

        private static readonly DependencyPropertyKey SelectedContentTemplatePropertyKey = DependencyProperty.RegisterReadOnly("SelectedContentTemplate", typeof(DataTemplate), typeof(TabControl), new FrameworkPropertyMetadata((DataTemplate)null));

        ///  
        ///     The DependencyProperty for the SelectedContentTemplate property.
        ///     Flags:              None 
        ///     Default Value:      null 
        /// 
        public static readonly DependencyProperty SelectedContentTemplateProperty = SelectedContentTemplatePropertyKey.DependencyProperty; 

        /// 
        ///     SelectedContentTemplate is the ContentTemplate of current SelectedItem.
        /// This property is updated whenever the selection is changed. 
        /// It always keeps a reference to active TabItem.ContentTemplate
        /// It is used for aliasing in default TabControl Style 
        ///  
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public DataTemplate SelectedContentTemplate
        {
            get
            { 
                return (DataTemplate)GetValue(SelectedContentTemplateProperty);
            } 
            internal set 
            {
                SetValue(SelectedContentTemplatePropertyKey, value); 
            }
        }

        private static readonly DependencyPropertyKey SelectedContentTemplateSelectorPropertyKey = DependencyProperty.RegisterReadOnly("SelectedContentTemplateSelector", typeof(DataTemplateSelector), typeof(TabControl), new FrameworkPropertyMetadata((DataTemplateSelector)null)); 

        ///  
        ///     The DependencyProperty for the SelectedContentTemplateSelector property. 
        ///     Flags:              None
        ///     Default Value:      null 
        /// 
        public static readonly DependencyProperty SelectedContentTemplateSelectorProperty = SelectedContentTemplateSelectorPropertyKey.DependencyProperty;

        ///  
        ///     SelectedContentTemplateSelector allows the app writer to provide custom style selection logic.
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public DataTemplateSelector SelectedContentTemplateSelector
        { 
            get
            {
                return (DataTemplateSelector)GetValue(SelectedContentTemplateSelectorProperty);
            } 
            internal set
            { 
                SetValue(SelectedContentTemplateSelectorPropertyKey, value); 
            }
        } 

        private static readonly DependencyPropertyKey SelectedContentStringFormatPropertyKey =
                DependencyProperty.RegisterReadOnly("SelectedContentStringFormat",
                        typeof(String), 
                        typeof(TabControl),
                        new FrameworkPropertyMetadata((String)null)); 
 
        /// 
        ///     The DependencyProperty for the SelectedContentStringFormat property. 
        ///     Flags:              None
        ///     Default Value:      null
        /// 
        public static readonly DependencyProperty SelectedContentStringFormatProperty = 
                SelectedContentStringFormatPropertyKey.DependencyProperty;
 
 
        /// 
        ///     ContentStringFormat is the format used to display the content of 
        ///     the control as a string.  This arises only when no template is
        ///     available.
        /// 
        public String SelectedContentStringFormat 
        {
            get { return (String) GetValue(SelectedContentStringFormatProperty); } 
            internal set { SetValue(SelectedContentStringFormatPropertyKey, value); } 
        }
 

        /// 
        ///     The DependencyProperty for the ContentTemplate property.
        ///     Flags:              None 
        ///     Default Value:      null
        ///  
        public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.Register("ContentTemplate", typeof(DataTemplate), typeof(TabControl), new FrameworkPropertyMetadata((DataTemplate)null)); 

        ///  
        /// ContentTemplate is the ContentTemplate to apply to TabItems
        /// that do not have the ContentTemplate or ContentTemplateSelector properties
        /// defined
        ///  
        /// 
        public DataTemplate ContentTemplate 
        { 
            get
            { 
                return (DataTemplate)GetValue(ContentTemplateProperty);
            }
            set
            { 
                SetValue(ContentTemplateProperty, value);
            } 
        } 

        ///  
        ///     The DependencyProperty for the ContentTemplateSelector property.
        ///     Flags:              None
        ///     Default Value:      null
        ///  
        public static readonly DependencyProperty ContentTemplateSelectorProperty = DependencyProperty.Register("ContentTemplateSelector", typeof(DataTemplateSelector), typeof(TabControl), new FrameworkPropertyMetadata((DataTemplateSelector)null));
 
        ///  
        ///     ContentTemplateSelector allows the app writer to provide custom style selection logic.
        ///  
        public DataTemplateSelector ContentTemplateSelector
        {
            get
            { 
                return (DataTemplateSelector)GetValue(ContentTemplateSelectorProperty);
            } 
            set 
            {
                SetValue(ContentTemplateSelectorProperty, value); 
            }
        }

        ///  
        ///     The DependencyProperty for the ContentStringFormat property.
        ///     Flags:              None 
        ///     Default Value:      null 
        /// 
        public static readonly DependencyProperty ContentStringFormatProperty = 
                DependencyProperty.Register(
                        "ContentStringFormat",
                        typeof(String),
                        typeof(TabControl), 
                        new FrameworkPropertyMetadata((String) null));
 
 
        /// 
        ///     ContentStringFormat is the format used to display the content of 
        ///     the control as a string.  This arises only when no template is
        ///     available.
        /// 
        public String ContentStringFormat 
        {
            get { return (String) GetValue(ContentStringFormatProperty); } 
            set { SetValue(ContentStringFormatProperty, value); } 
        }
 
        #endregion

        #region Overrided Methods
 
        /// 
        /// Creates AutomationPeer () 
        ///  
        protected override AutomationPeer OnCreateAutomationPeer()
        { 
            return new TabControlAutomationPeer(this);
        }

        ///  
        ///     This virtual method in called when IsInitialized is set to true and it raises an Initialized event
        ///  
        protected override void OnInitialized(EventArgs e) 
        {
            base.OnInitialized(e); 
            CanSelectMultiple = false;
            ItemContainerGenerator.StatusChanged += new EventHandler(OnGeneratorStatusChanged);
        }
        ///  
        /// Called when the Template's tree has been generated. When Template gets expanded we ensure that SelectedContent is in [....]
        ///  
        public override void OnApplyTemplate() 
        {
            base.OnApplyTemplate(); 
            UpdateSelectedContent();
        }

        ///  
        /// A virtual function that is called when the selection is changed. Default behavior
        /// is to raise a SelectionChangedEvent 
        ///  
        /// The inputs for this event. Can be raised (default behavior) or processed
        ///   in some other way. 
        protected override void OnSelectionChanged(SelectionChangedEventArgs e)
        {
            base.OnSelectionChanged(e);
            if (IsKeyboardFocusWithin) 
            {
                // If keyboard focus is within the control, make sure it is going to the correct place 
                TabItem item = GetSelectedTabItem(); 
                if (item != null)
                { 
                    item.SetFocus();
                }
            }
            UpdateSelectedContent(); 

            if (    AutomationPeer.ListenerExists(AutomationEvents.SelectionPatternOnInvalidated) 
                ||  AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementSelected) 
                ||  AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementAddedToSelection)
                ||  AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementRemovedFromSelection)   ) 
            {
                TabControlAutomationPeer peer = UIElementAutomationPeer.CreatePeerForElement(this) as TabControlAutomationPeer;
                if (peer != null)
                    peer.RaiseSelectionEvents(e); 
            }
        } 
 
        /// 
        /// Updates the current selection when Items has changed 
        /// 
        /// Information about what has changed
        protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
        { 
            base.OnItemsChanged(e);
            if (e.Action == NotifyCollectionChangedAction.Remove && SelectedIndex == -1) 
            { 
                // If we remove the selected item we should select the previous item
                int startIndex = e.OldStartingIndex + 1; 
                if (startIndex > Items.Count)
                    startIndex = 0;
                TabItem nextTabItem = FindNextTabItem(startIndex, -1);
                if (nextTabItem != null) 
                    nextTabItem.IsSelected = true;
            } 
        } 

        ///  
        /// This is the method that responds to the KeyDown event.
        /// 
        /// 
        protected override void OnKeyDown(KeyEventArgs e) 
        {
            TabItem nextTabItem = null; 
 
            // Handle [Ctrl][Shift]Tab, Home and End cases
            // We have special handling here because if focus is inside the TabItem content we cannot 
            // cycle through TabItem because the content is not part of the TabItem visual tree

            int direction = 0;
            int startIndex = -1; 
            switch (e.Key)
            { 
                case Key.Tab: 
                    if ((e.KeyboardDevice.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                    { 
                        startIndex = ItemContainerGenerator.IndexFromContainer(ItemContainerGenerator.ContainerFromItem(SelectedItem));
                        if ((e.KeyboardDevice.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
                            direction = -1;
                        else 
                            direction = 1;
                    } 
                    break; 
                case Key.Home:
                    direction = 1; 
                    startIndex = -1;
                    break;
                case Key.End:
                    direction = -1; 
                    startIndex = Items.Count;
                    break; 
            } 

            nextTabItem = FindNextTabItem(startIndex, direction); 

            if (nextTabItem != null && nextTabItem != SelectedItem)
            {
                e.Handled = nextTabItem.SetFocus(); 
            }
 
            if (!e.Handled) 
                base.OnKeyDown(e);
        } 

        private TabItem FindNextTabItem(int startIndex, int direction)
        {
            TabItem nextTabItem = null; 
            if (direction != 0)
            { 
                int index = startIndex; 
                for (int i = 0; i < Items.Count; i++)
                { 
                    index += direction;
                    if (index >= Items.Count)
                        index = 0;
                    else if (index < 0) 
                        index = Items.Count - 1;
 
                    TabItem tabItem = ItemContainerGenerator.ContainerFromIndex(index) as TabItem; 
                    if (tabItem != null && tabItem.IsEnabled && tabItem.Visibility == Visibility.Visible)
                    { 
                        nextTabItem = tabItem;
                        break;
                    }
                } 
            }
            return nextTabItem; 
        } 

        ///  
        /// Return true if the item is (or is eligible to be) its own ItemUI
        /// 
        protected override bool IsItemItsOwnContainerOverride(object item)
        { 
            return (item is TabItem);
        } 
 
        ///  Create or identify the element used to display the given item. 
        protected override DependencyObject GetContainerForItemOverride() 
        {
            return new TabItem();
        }
 
        #endregion
 
        #region private helpers 

        internal ContentPresenter SelectedContentPresenter 
        {
            get
            {
                return GetTemplateChild(SelectedContentHostTemplateName) as ContentPresenter; 
            }
        } 
 
        private void OnGeneratorStatusChanged(object sender, EventArgs e)
        { 
            if (ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
            {
                if (HasItems && _selectedItems.Count == 0)
                { 
                    SelectedIndex = 0;
                } 
 
                UpdateSelectedContent();
            } 
        }

        private TabItem GetSelectedTabItem()
        { 
            object selectedItem = SelectedItem;
            if (selectedItem != null) 
            { 
                // Check if the selected item is a TabItem
                TabItem tabItem = selectedItem as TabItem; 
                if (tabItem == null)
                {
                    // It is a data item, get its TabItem container
                    tabItem = ItemContainerGenerator.ContainerFromIndex(SelectedIndex) as TabItem; 
                }
 
                return tabItem; 
            }
 
            return null;
        }

        // When selection is changed we need to copy the active TabItem content in SelectedContent property 
        // SelectedContent is aliased in the TabControl style
        private void UpdateSelectedContent() 
        { 
            if (SelectedIndex < 0)
            { 
                SelectedContent = null;
                SelectedContentTemplate = null;
                SelectedContentTemplateSelector = null;
                SelectedContentStringFormat = null; 
                return;
            } 
 
            TabItem tabItem = GetSelectedTabItem();
            if (tabItem != null) 
            {
                FrameworkElement visualParent = VisualTreeHelper.GetParent(tabItem) as FrameworkElement;

                if (visualParent != null) 
                {
                    KeyboardNavigation.SetTabOnceActiveElement(visualParent, tabItem); 
                    KeyboardNavigation.SetTabOnceActiveElement(this, visualParent); 
                }
 
                SelectedContent = tabItem.Content;
                ContentPresenter scp = SelectedContentPresenter;
                if (scp != null)
                { 
                    scp.HorizontalAlignment = tabItem.HorizontalContentAlignment;
                    scp.VerticalAlignment = tabItem.VerticalContentAlignment; 
                } 

                // Use tabItem's template or selector if specified, otherwise use TabControl's 
                if (tabItem.ContentTemplate != null || tabItem.ContentTemplateSelector != null || tabItem.ContentStringFormat != null)
                {
                    SelectedContentTemplate = tabItem.ContentTemplate;
                    SelectedContentTemplateSelector = tabItem.ContentTemplateSelector; 
                    SelectedContentStringFormat = tabItem.ContentStringFormat;
                } 
                else 
                {
                    SelectedContentTemplate = ContentTemplate; 
                    SelectedContentTemplateSelector = ContentTemplateSelector;
                    SelectedContentStringFormat = ContentStringFormat;
                }
             } 
        }
 
        #endregion private helpers 

        #region private data 

        // Part name used in the style. The class TemplatePartAttribute should use the same name
        private const string SelectedContentHostTemplateName = "PART_SelectedContentHost";
 
        #endregion
 
        #region DTypeThemeStyleKey 

        // Returns the DependencyObjectType for the registered ThemeStyleKey's default 
        // value. Controls will override this method to return approriate types.
        internal override DependencyObjectType DTypeThemeStyleKey
        {
            get { return _dType; } 
        }
 
        private static DependencyObjectType _dType; 

        #endregion DTypeThemeStyleKey 
    }
}


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK