Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / TabControl.cs / 1305600 / 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)); IsEnabledProperty.OverrideMetadata(typeof(TabControl), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); } ////// 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 internal override void ChangeVisualState(bool useTransitions) { if (!IsEnabled) { VisualStates.GoToState(this, useTransitions, VisualStates.StateDisabled, VisualStates.StateNormal); } else { VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions); } base.ChangeVisualState(useTransitions); } ////// 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.SetCurrentValueInternal(TabItem.IsSelectedProperty, MS.Internal.KnownBoxes.BooleanBoxes.TrueBox); } } ////// 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) { SetCurrentValueInternal(SelectedIndexProperty, 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; // Due to event leapfrogging, we may have the wrong container. // If so, re-fetch the right container using a more expensive method. // (BTW, the previous line will cause a debug assert in this case) [Dev10 452711] if (tabItem != null && !Object.Equals(selectedItem, ItemContainerGenerator.ItemFromContainer(tabItem))) { tabItem = ItemContainerGenerator.ContainerFromItem(selectedItem) 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)); IsEnabledProperty.OverrideMetadata(typeof(TabControl), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); } ////// 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 internal override void ChangeVisualState(bool useTransitions) { if (!IsEnabled) { VisualStates.GoToState(this, useTransitions, VisualStates.StateDisabled, VisualStates.StateNormal); } else { VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions); } base.ChangeVisualState(useTransitions); } ////// 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.SetCurrentValueInternal(TabItem.IsSelectedProperty, MS.Internal.KnownBoxes.BooleanBoxes.TrueBox); } } ////// 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) { SetCurrentValueInternal(SelectedIndexProperty, 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; // Due to event leapfrogging, we may have the wrong container. // If so, re-fetch the right container using a more expensive method. // (BTW, the previous line will cause a debug assert in this case) [Dev10 452711] if (tabItem != null && !Object.Equals(selectedItem, ItemContainerGenerator.ItemFromContainer(tabItem))) { tabItem = ItemContainerGenerator.ContainerFromItem(selectedItem) 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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SimpleType.cs
- DispatchOperation.cs
- MachinePropertyVariants.cs
- EdmProviderManifest.cs
- FunctionCommandText.cs
- ReadOnlyState.cs
- Int16Storage.cs
- SplitterCancelEvent.cs
- x509utils.cs
- precedingsibling.cs
- TakeOrSkipQueryOperator.cs
- NativeObjectSecurity.cs
- Models.cs
- MenuItemStyle.cs
- FlowDocumentFormatter.cs
- BigIntegerStorage.cs
- AdornedElementPlaceholder.cs
- cache.cs
- HorizontalAlignConverter.cs
- FlowLayoutSettings.cs
- assemblycache.cs
- SqlDependencyUtils.cs
- FreezableDefaultValueFactory.cs
- LingerOption.cs
- UIElementParaClient.cs
- DictionarySectionHandler.cs
- MSAAEventDispatcher.cs
- CursorConverter.cs
- AllMembershipCondition.cs
- TreeNodeEventArgs.cs
- ParameterEditorUserControl.cs
- Menu.cs
- SafeNativeMethods.cs
- BooleanToVisibilityConverter.cs
- BitmapSizeOptions.cs
- TextEffect.cs
- metadatamappinghashervisitor.cs
- WebPart.cs
- NamespaceDecl.cs
- ToolBarPanel.cs
- OdbcUtils.cs
- TextBlock.cs
- XmlImplementation.cs
- HwndAppCommandInputProvider.cs
- SkewTransform.cs
- CompoundFileStorageReference.cs
- Tile.cs
- InstalledFontCollection.cs
- FormViewRow.cs
- ObjectStateEntryDbUpdatableDataRecord.cs
- Viewport3DVisual.cs
- OrderByQueryOptionExpression.cs
- Base64Decoder.cs
- LocalizeDesigner.cs
- EventRouteFactory.cs
- ButtonFlatAdapter.cs
- SortKey.cs
- ExtensibleClassFactory.cs
- UriScheme.cs
- Geometry3D.cs
- HideDisabledControlAdapter.cs
- Translator.cs
- QueryServiceConfigHandle.cs
- QueryPageSettingsEventArgs.cs
- MessagePropertyAttribute.cs
- DataRowView.cs
- PenContexts.cs
- IntAverageAggregationOperator.cs
- EndPoint.cs
- DocumentAutomationPeer.cs
- CaseCqlBlock.cs
- ProvidersHelper.cs
- RuntimeConfigurationRecord.cs
- _NestedSingleAsyncResult.cs
- Asn1IntegerConverter.cs
- XsltLoader.cs
- TextBoxDesigner.cs
- ListControlBuilder.cs
- EntitySetDataBindingList.cs
- CodeParameterDeclarationExpression.cs
- ChooseAction.cs
- XmlSchemaFacet.cs
- BuilderPropertyEntry.cs
- DateBoldEvent.cs
- TdsParserStaticMethods.cs
- XPathException.cs
- PropertySegmentSerializationProvider.cs
- StatusBar.cs
- DeflateEmulationStream.cs
- HttpWebRequest.cs
- SessionStateUtil.cs
- SecurityDocument.cs
- ObjectDataSourceMethodEventArgs.cs
- WebPartConnection.cs
- DrawingAttributes.cs
- HwndPanningFeedback.cs
- SqlAliaser.cs
- PixelShader.cs
- CustomError.cs
- XmlConvert.cs