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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- KeyConstraint.cs
- PartitionedDataSource.cs
- WebPartConnectVerb.cs
- CheckBoxPopupAdapter.cs
- DefaultHttpHandler.cs
- WorkflowNamespace.cs
- Screen.cs
- Main.cs
- Content.cs
- MessageDecoder.cs
- ContentPresenter.cs
- GetCertificateRequest.cs
- EmptyStringExpandableObjectConverter.cs
- TextTreeTextBlock.cs
- CodeMethodMap.cs
- ISCIIEncoding.cs
- StreamingContext.cs
- ActivityBindForm.cs
- QueryAccessibilityHelpEvent.cs
- LinqDataSourceHelper.cs
- IndependentlyAnimatedPropertyMetadata.cs
- Splitter.cs
- CreateUserWizardStep.cs
- ValueUtilsSmi.cs
- GroupItemAutomationPeer.cs
- SortDescription.cs
- SqlTypesSchemaImporter.cs
- ListBoxAutomationPeer.cs
- LicenseManager.cs
- ScriptingJsonSerializationSection.cs
- DialogResultConverter.cs
- FormsAuthenticationConfiguration.cs
- ReadOnlyActivityGlyph.cs
- TemplateApplicationHelper.cs
- BamlVersionHeader.cs
- TableRowCollection.cs
- ExpressionBuilder.cs
- DataSourceCacheDurationConverter.cs
- RefreshPropertiesAttribute.cs
- PointAnimationUsingPath.cs
- URI.cs
- DataGridViewSelectedRowCollection.cs
- EventProperty.cs
- SiteMap.cs
- FormsAuthenticationEventArgs.cs
- SoapCodeExporter.cs
- ClientOptions.cs
- LookupBindingPropertiesAttribute.cs
- HTMLTextWriter.cs
- CodeNamespaceCollection.cs
- ByteConverter.cs
- PropertyTab.cs
- SchemaRegistration.cs
- RelationalExpressions.cs
- ThousandthOfEmRealDoubles.cs
- ComponentCollection.cs
- SqlFlattener.cs
- ButtonAutomationPeer.cs
- TabControl.cs
- CopyNamespacesAction.cs
- ExpressionList.cs
- TripleDESCryptoServiceProvider.cs
- XmlIlVisitor.cs
- Rotation3D.cs
- Executor.cs
- ChannelSinkStacks.cs
- NameValuePair.cs
- NoneExcludedImageIndexConverter.cs
- Types.cs
- PolyBezierSegment.cs
- SubclassTypeValidator.cs
- CustomErrorsSection.cs
- StrokeSerializer.cs
- NumericExpr.cs
- TemplateBindingExpression.cs
- EditorPart.cs
- CacheModeValueSerializer.cs
- TypeElement.cs
- EntityContainerAssociationSet.cs
- HebrewNumber.cs
- WebServiceErrorEvent.cs
- HtmlContainerControl.cs
- StatusBarAutomationPeer.cs
- MetafileHeaderEmf.cs
- DocumentOrderComparer.cs
- TableItemStyle.cs
- DefaultValueConverter.cs
- XmlTextReader.cs
- ReliableSession.cs
- Point3DCollection.cs
- WorkflowPersistenceService.cs
- Parallel.cs
- OuterProxyWrapper.cs
- EventLog.cs
- Int64KeyFrameCollection.cs
- ExtendedProperty.cs
- HttpServerVarsCollection.cs
- TextShapeableCharacters.cs
- Baml2006SchemaContext.cs
- SequentialUshortCollection.cs