TabItem.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / TabItem.cs / 1407647 / TabItem.cs

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

using System; 
using System.Diagnostics; 
using MS.Internal;
using MS.Internal.KnownBoxes; 
using MS.Utility;
using System.Windows.Threading;
using System.ComponentModel;
using System.Windows.Automation; 
using System.Windows.Automation.Peers;
using System.Windows.Media; 
using System.Windows.Input; 
using System.Windows;
using System.Windows.Data; 

using System.Windows.Controls.Primitives;

// Disable CS3001: Warning as Error: not CLS-compliant 
#pragma warning disable 3001
 
namespace System.Windows.Controls 
{
    ///  
    ///     A child item of TabControl.
    /// 
    [DefaultEvent("IsSelectedChanged")]
    public class TabItem : HeaderedContentControl 
    {
        //------------------------------------------------------------------- 
        // 
        //  Constructors
        // 
        //-------------------------------------------------------------------

        #region Constructors
 
        /// 
        ///     Default DependencyObject constructor 
        ///  
        /// 
        ///     Automatic determination of current Dispatcher. Use alternative constructor 
        ///     that accepts a Dispatcher for best performance.
        /// 
        public TabItem() : base()
        { 
        }
 
        static TabItem() 
        {
            EventManager.RegisterClassHandler(typeof(TabItem), AccessKeyManager.AccessKeyPressedEvent, new AccessKeyPressedEventHandler(OnAccessKeyPressed)); 

            DefaultStyleKeyProperty.OverrideMetadata(typeof(TabItem), new FrameworkPropertyMetadata(typeof(TabItem)));
            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(TabItem));
            KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(TabItem), new FrameworkPropertyMetadata(KeyboardNavigationMode.Contained)); 
            KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(TabItem), new FrameworkPropertyMetadata(KeyboardNavigationMode.Local));
 
            IsEnabledProperty.OverrideMetadata(typeof(TabItem), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); 
            IsMouseOverPropertyKey.OverrideMetadata(typeof(TabItem), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged)));
        } 

        #endregion

        //-------------------------------------------------------------------- 
        //
        //  Properties 
        // 
        //-------------------------------------------------------------------
 
        #region Properties
        /// 
        ///     Indicates whether this TabItem is selected.
        ///  
        public static readonly DependencyProperty IsSelectedProperty =
                Selector.IsSelectedProperty.AddOwner(typeof(TabItem), 
                        new FrameworkPropertyMetadata(BooleanBoxes.FalseBox, 
                                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.AffectsParentMeasure | FrameworkPropertyMetadataOptions.Journal,
                                new PropertyChangedCallback(OnIsSelectedChanged))); 

        /// 
        ///     Indicates whether this TabItem is selected.
        ///  
        [Bindable(true), Category("Appearance")]
        public bool IsSelected 
        { 
            get { return (bool) GetValue(IsSelectedProperty); }
            set { SetValue(IsSelectedProperty, BooleanBoxes.Box(value)); } 
        }

        private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            TabItem tabItem = d as TabItem;
 
            bool isSelected = (bool)e.NewValue; 

            TabControl parentTabControl = tabItem.TabControlParent; 
            if (parentTabControl != null)
            {
                parentTabControl.RaiseIsSelectedChangedAutomationEvent(tabItem, isSelected);
            } 

            if (isSelected) 
            { 
                tabItem.OnSelected(new RoutedEventArgs(Selector.SelectedEvent, tabItem));
            } 
            else
            {
                tabItem.OnUnselected(new RoutedEventArgs(Selector.UnselectedEvent, tabItem));
            } 

 
            // KeyboardNavigation use bounding box reduced with DirectionalNavigationMargin when calculating the next element in directional navigation 
            // Because TabItem use negative margins some TabItems overlap which would changes the directional navigation if we don't reduce the bounding box
            if (isSelected) 
            {
                Binding binding = new Binding("Margin");
                binding.Source = tabItem;
                BindingOperations.SetBinding(tabItem, KeyboardNavigation.DirectionalNavigationMarginProperty, binding); 
            }
            else 
            { 
                BindingOperations.ClearBinding(tabItem, KeyboardNavigation.DirectionalNavigationMarginProperty);
            } 

            tabItem.UpdateVisualState();
        }
 
        /// 
        ///     Event indicating that the IsSelected property is now true. 
        ///  
        /// Event arguments
        protected virtual void OnSelected(RoutedEventArgs e) 
        {
            HandleIsSelectedChanged(true, e);
        }
 
        /// 
        ///     Event indicating that the IsSelected property is now false. 
        ///  
        /// Event arguments
        protected virtual void OnUnselected(RoutedEventArgs e) 
        {
            HandleIsSelectedChanged(false, e);
        }
 
        private void HandleIsSelectedChanged(bool newValue, RoutedEventArgs e)
        { 
#if OLD_AUTOMATION 
            if (AutomationProvider.IsActive)
            { 
                RaiseAutomationIsSelectedChanged(!newValue, newValue);
            }
#endif
 
            RaiseEvent(e);
        } 
 
#if OLD_AUTOMATION
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 
        private void RaiseAutomationIsSelectedChanged(bool oldValue, bool newValue)
        {
            AutomationProvider.RaiseAutomationPropertyChangedEvent(this, SelectionItemPatternIdentifiers.IsSelectedProperty, oldValue, newValue);
        } 
#endif
 
        #region TabStripPlacement 
        /// 
        ///     Property key for TabStripPlacementProperty. 
        /// 
        private static readonly DependencyPropertyKey TabStripPlacementPropertyKey =
                DependencyProperty.RegisterReadOnly(
                        "TabStripPlacement", 
                        typeof(Dock),
                        typeof(TabItem), 
                        new FrameworkPropertyMetadata( 
                                Dock.Top,
                                null, 
                                new CoerceValueCallback(CoerceTabStripPlacement)));

        /// 
        /// Specifies the placement of the TabItem 
        /// 
        public static readonly DependencyProperty TabStripPlacementProperty = 
            TabStripPlacementPropertyKey.DependencyProperty; 

        private static object CoerceTabStripPlacement(DependencyObject d, object value) 
        {
            TabControl tabControl = ((TabItem)d).TabControlParent;
            return (tabControl != null) ? tabControl.TabStripPlacement : value;
        } 

        ///  
        /// Specifies the placement of the TabItem. This read-only property get its value from the TabControl parent 
        /// 
        public Dock TabStripPlacement 
        {
            get
            {
                return (Dock)GetValue(TabStripPlacementProperty); 
            }
        } 
 
        internal override void OnAncestorChanged()
        { 
            // TabStripPlacement depends on the logical parent -- so invalidate it when that changes
            CoerceValue(TabStripPlacementProperty);
        }
 
        #endregion TabStripPlacement
 
        #endregion 

        //-------------------------------------------------------------------- 
        //
        //  Protected Methods
        //
        //-------------------------------------------------------------------- 

        #region Protected Methods 
 
        internal override void ChangeVisualState(bool useTransitions)
        { 
            if (!IsEnabled)
            {
                VisualStateManager.GoToState(this, VisualStates.StateDisabled, useTransitions);
            } 
            else if (IsMouseOver)
            { 
                VisualStateManager.GoToState(this, VisualStates.StateMouseOver, useTransitions); 
            }
            else 
            {
                VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions);
            }
 
            // Update the SelectionStates group
            if (IsSelected) 
            { 
                VisualStates.GoToState(this, useTransitions, VisualStates.StateSelected, VisualStates.StateUnselected);
            } 
            else
            {
                VisualStateManager.GoToState(this, VisualStates.StateUnselected, useTransitions);
            } 

            if (IsKeyboardFocused) 
            { 
                VisualStateManager.GoToState(this, VisualStates.StateFocused, useTransitions);
            } 
            else
            {
                VisualStateManager.GoToState(this, VisualStates.StateUnfocused, useTransitions);
            } 

            base.ChangeVisualState(useTransitions); 
        } 

        ///  
        /// Creates AutomationPeer ()
        /// 
        protected override AutomationPeer OnCreateAutomationPeer()
        { 
            return new TabItemWrapperAutomationPeer(this);
        } 
 
        /// 
        /// This is the method that responds to the MouseLeftButtonDownEvent event. 
        /// 
        /// 
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        { 
            // We should process only the direct events in case TabItem is the selected one
            // otherwise we are getting this event when we click on TabItem content because it is in the logical subtree 
            if (e.Source == this || !IsSelected) 
            {
                if (SetFocus()) 
                    e.Handled = true;
            }
            base.OnMouseLeftButtonDown(e);
        } 

        ///  
        /// Focus event handler 
        /// 
        ///  
        protected override void OnPreviewGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
        {
            base.OnPreviewGotKeyboardFocus(e);
            if (!e.Handled && e.NewFocus == this) 
            {
                if (!IsSelected && TabControlParent != null) 
                { 
                    SetCurrentValueInternal(IsSelectedProperty, BooleanBoxes.TrueBox);
                    // If focus moved in result of selection - handle the event to prevent setting focus back on the new item 
                    if (e.OldFocus != Keyboard.FocusedElement)
                    {
                        e.Handled = true;
                    } 
                    else if (GetBoolField(BoolField.SetFocusOnContent))
                    { 
                        TabControl parentTabControl = TabControlParent; 
                        if (parentTabControl != null)
                        { 
                            // Save the parent and check for null to make sure that SetCurrentValue didn't have a change handler
                            // that removed the TabItem from the tree.
                            ContentPresenter selectedContentPresenter = parentTabControl.SelectedContentPresenter;
                            if (selectedContentPresenter != null) 
                            {
                                parentTabControl.UpdateLayout(); // Wait for layout 
                                bool success = selectedContentPresenter.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); 

                                // If we successfully move focus inside the content then don't set focus to the header 
                                if (success)
                                    e.Handled = true;
                            }
                        } 
                    }
                } 
            } 
        }
 
        /// 
        /// The Access key for this control was invoked.
        /// 
        protected override void OnAccessKey(AccessKeyEventArgs e) 
        {
            SetFocus(); 
        } 

        ///  
        ///     This method is invoked when the Content property changes.
        /// 
        /// The old value of the Content property.
        /// The new value of the Content property. 
        protected override void OnContentChanged(object oldContent, object newContent)
        { 
            base.OnContentChanged(oldContent, newContent); 

            // If this is the selected TabItem then we should update TabControl.SelectedContent 
            if (IsSelected)
            {
                TabControl tabControl = TabControlParent;
                if (tabControl != null) 
                {
                    tabControl.SelectedContent = newContent; 
                } 
            }
        } 

        /// 
        ///     This method is invoked when the ContentTemplate property changes.
        ///  
        /// The old value of the ContentTemplate property.
        /// The new value of the ContentTemplate property. 
        protected override void OnContentTemplateChanged(DataTemplate oldContentTemplate, DataTemplate newContentTemplate) 
        {
            base.OnContentTemplateChanged(oldContentTemplate, newContentTemplate); 

            // If this is the selected TabItem then we should update TabControl.SelectedContentTemplate
            if (IsSelected)
            { 
                TabControl tabControl = TabControlParent;
                if (tabControl != null) 
                { 
                    tabControl.SelectedContentTemplate = newContentTemplate;
                } 
            }
        }

        ///  
        ///     This method is invoked when the ContentTemplateSelector property changes.
        ///  
        /// The old value of the ContentTemplateSelector property. 
        /// The new value of the ContentTemplateSelector property.
        protected override void OnContentTemplateSelectorChanged(DataTemplateSelector oldContentTemplateSelector, DataTemplateSelector newContentTemplateSelector) 
        {
            base.OnContentTemplateSelectorChanged(oldContentTemplateSelector, newContentTemplateSelector);

            // If this is the selected TabItem then we should update TabControl.SelectedContentTemplateSelector 
            if (IsSelected)
            { 
                TabControl tabControl = TabControlParent; 
                if (tabControl != null)
                { 
                    tabControl.SelectedContentTemplateSelector = newContentTemplateSelector;
                }
            }
        } 

        #endregion 
 
        //-------------------------------------------------------------------
        // 
        //  Private Methods
        //
        //--------------------------------------------------------------------
 
        #region Private Methods
 
        private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) 
        {
            if (!e.Handled && e.Scope == null) 
            {
                TabItem tabItem = sender as TabItem;

                if (e.Target == null) 
                {
                    e.Target = tabItem; 
                } 
                else if (!tabItem.IsSelected) // If TabItem is not active it is a scope for its content elements
                { 
                    e.Scope = tabItem;
                    e.Handled = true;
                }
            } 
        }
 
        internal bool SetFocus() 
        {
            bool returnValue = false; 

            if (!GetBoolField(BoolField.SettingFocus))
            {
                TabItem currentFocus = Keyboard.FocusedElement as TabItem; 

                // If current focus was another TabItem in the same TabControl - dont set focus on content 
                bool setFocusOnContent = ((currentFocus == this) || (currentFocus == null) || (currentFocus.TabControlParent != this.TabControlParent)); 
                SetBoolField(BoolField.SettingFocus, true);
                SetBoolField(BoolField.SetFocusOnContent, setFocusOnContent); 
                try
                {
                    returnValue = Focus() || setFocusOnContent;
                } 
                finally
                { 
                    SetBoolField(BoolField.SettingFocus, false); 
                    SetBoolField(BoolField.SetFocusOnContent, false);
                } 
            }

            return returnValue;
        } 

        private TabControl TabControlParent 
        { 
            get
            { 
                return ItemsControl.ItemsControlFromItemContainer(this) as TabControl;
            }
        }
 
        #endregion
 
        //------------------------------------------------------------------- 
        //
        //  Private Fields 
        //
        //-------------------------------------------------------------------

        #region Private Fields 

        private bool GetBoolField(BoolField field) 
        { 
            return (_tabItemBoolFieldStore & field) != 0;
        } 

        private void SetBoolField(BoolField field, bool value)
        {
            if (value) 
            {
                _tabItemBoolFieldStore |= field; 
            } 
            else
            { 
                _tabItemBoolFieldStore &= (~field);
            }
        }
 
        [Flags]
        private enum BoolField 
        { 
            SetFocusOnContent      = 0x10, // This flag determine if we want to set focus on active TabItem content
            SettingFocus           = 0x20, // This flag indicates that the TabItem is in the process of setting focus 

            // By default ListBoxItem is selectable
            DefaultValue = 0,
        } 

        BoolField _tabItemBoolFieldStore = BoolField.DefaultValue; 
 
        #endregion Private Fields
 
        #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