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
- DataFieldConverter.cs
- MapPathBasedVirtualPathProvider.cs
- RangeValuePatternIdentifiers.cs
- StorageTypeMapping.cs
- StringDictionaryEditor.cs
- TextBox.cs
- DeploymentSection.cs
- TextRenderer.cs
- DebugView.cs
- Padding.cs
- EventManager.cs
- XmlILIndex.cs
- ReachIDocumentPaginatorSerializerAsync.cs
- SafeNativeMethods.cs
- TreeViewTemplateSelector.cs
- BindingWorker.cs
- EtwProvider.cs
- HTMLTextWriter.cs
- ClientApiGenerator.cs
- EpmSyndicationContentSerializer.cs
- LocalizationCodeDomSerializer.cs
- FatalException.cs
- ValidatedControlConverter.cs
- SimpleFileLog.cs
- MenuItem.cs
- SqlDataRecord.cs
- BroadcastEventHelper.cs
- ColumnResizeUndoUnit.cs
- ExcCanonicalXml.cs
- StyleTypedPropertyAttribute.cs
- XamlPointCollectionSerializer.cs
- ExtensionQuery.cs
- BaseAddressPrefixFilterElement.cs
- DataGridViewElement.cs
- InputBuffer.cs
- Single.cs
- SqlEnums.cs
- TextRange.cs
- processwaithandle.cs
- NoneExcludedImageIndexConverter.cs
- Exceptions.cs
- HintTextConverter.cs
- ContextItem.cs
- ExtendedPropertyDescriptor.cs
- SiteOfOriginContainer.cs
- XmlAttributeAttribute.cs
- Int32Collection.cs
- UriParserTemplates.cs
- DataGridCaption.cs
- namescope.cs
- RelationshipEntry.cs
- Brushes.cs
- HttpWebResponse.cs
- xml.cs
- Authorization.cs
- UITypeEditor.cs
- FamilyTypeface.cs
- FixedHighlight.cs
- PathSegment.cs
- SQLInt16.cs
- OleDbError.cs
- sqlcontext.cs
- NegotiationTokenAuthenticatorState.cs
- TriggerAction.cs
- XmlSchemaImporter.cs
- RuntimeCompatibilityAttribute.cs
- _HeaderInfoTable.cs
- Highlights.cs
- VerificationAttribute.cs
- printdlgexmarshaler.cs
- ClientRolePrincipal.cs
- _TLSstream.cs
- EditingScope.cs
- DoubleUtil.cs
- SqlDataSourceCommandEventArgs.cs
- EventItfInfo.cs
- SqlDataSourceCommandEventArgs.cs
- WorkflowRuntimeServiceElement.cs
- DateTimeFormatInfo.cs
- SafeArrayRankMismatchException.cs
- TabControl.cs
- EncodingInfo.cs
- ContainsRowNumberChecker.cs
- BaseCollection.cs
- FacetValues.cs
- TitleStyle.cs
- EntityType.cs
- NumberSubstitution.cs
- _NegotiateClient.cs
- ToolStripSeparator.cs
- XmlQueryContext.cs
- JsonDeserializer.cs
- ServiceInfo.cs
- SqlTransaction.cs
- Error.cs
- TabRenderer.cs
- DataGridItemAttachedStorage.cs
- HostVisual.cs
- ComboBox.cs
- StandardOleMarshalObject.cs