Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / ToolBar.cs / 1458001 / ToolBar.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Windows.Threading; using System.Windows; using System.Windows.Automation; using System.Windows.Automation.Peers; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using System.Windows.Markup; using System.Windows.Shapes; using MS.Utility; using MS.Internal.KnownBoxes; namespace System.Windows.Controls { #region public enum types ////// Defines how we place the toolbar items /// public enum OverflowMode { ////// specifies that the item moves between the main and the overflow panels as space permits /// AsNeeded, ////// specifies that the item is permanently placed in the overflow panel /// Always, ////// specifies that the item is never allowed to overflow /// Never // NOTE: if you add or remove any values in this enum, be sure to update ToolBar.IsValidOverflowMode() } #endregion public enum types ////// ToolBar provides an overflow mechanism which places any items that doesnt fit naturally /// fit within a size-constrained ToolBar into a special overflow area. /// Also, ToolBars have a tight relationship with the related ToolBarTray control. /// [TemplatePart(Name = "PART_ToolBarPanel", Type = typeof(ToolBarPanel))] [TemplatePart(Name = "PART_ToolBarOverflowPanel", Type = typeof(ToolBarOverflowPanel))] public class ToolBar : HeaderedItemsControl { #region Constructors static ToolBar() { // Disable tooltips on toolbar when the overflow is open ToolTipService.IsEnabledProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CoerceToolTipIsEnabled))); DefaultStyleKeyProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(typeof(ToolBar))); _dType = DependencyObjectType.FromSystemTypeInternal(typeof(ToolBar)); IsTabStopProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(MS.Internal.KnownBoxes.BooleanBoxes.FalseBox)); FocusableProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(MS.Internal.KnownBoxes.BooleanBoxes.FalseBox)); KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle)); KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle)); KeyboardNavigation.ControlTabNavigationProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once)); FocusManager.IsFocusScopeProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(BooleanBoxes.TrueBox)); EventManager.RegisterClassHandler(typeof(ToolBar), Mouse.MouseDownEvent, new MouseButtonEventHandler(OnMouseButtonDown), true); EventManager.RegisterClassHandler(typeof(ToolBar), ButtonBase.ClickEvent, new RoutedEventHandler(_OnClick)); } ////// Default ToolBar constructor /// ////// Automatic determination of current Dispatcher. Use alternative constructor /// that accepts a Dispatcher for best performance. /// public ToolBar() : base() { } #endregion #region Properties #region Orientation ////// Property key for OrientationProperty. /// private static readonly DependencyPropertyKey OrientationPropertyKey = DependencyProperty.RegisterAttachedReadOnly( "Orientation", typeof(Orientation), typeof(ToolBar), new FrameworkPropertyMetadata( Orientation.Horizontal, null, new CoerceValueCallback(CoerceOrientation))); ////// Specifies the orientation (horizontal or vertical) of the flow /// public static readonly DependencyProperty OrientationProperty = OrientationPropertyKey.DependencyProperty; private static object CoerceOrientation(DependencyObject d, object value) { ToolBarTray toolBarTray = ((ToolBar) d).ToolBarTray; return (toolBarTray != null) ? toolBarTray.Orientation : value; } ////// Specifies the orientation of the ToolBar. This read-only property get its value from the ToolBarTray parent /// public Orientation Orientation { get { return (Orientation) GetValue(OrientationProperty); } } #endregion Orientation #region Band ////// Specify the band number where ToolBar should be located withing the ToolBarTray /// public static readonly DependencyProperty BandProperty = DependencyProperty.Register( "Band", typeof(int), typeof(ToolBar), new FrameworkPropertyMetadata( 0, FrameworkPropertyMetadataOptions.AffectsParentMeasure)); ////// Specify the band number where ToolBar should be located withing the ToolBarTray /// ///public int Band { get { return (int) GetValue(BandProperty); } set { SetValue(BandProperty, value); } } #endregion Band #region BandIndex /// /// Specify the band index number where ToolBar should be located within the band of ToolBarTray /// public static readonly DependencyProperty BandIndexProperty = DependencyProperty.Register( "BandIndex", typeof(int), typeof(ToolBar), new FrameworkPropertyMetadata( 0, FrameworkPropertyMetadataOptions.AffectsParentMeasure)); ////// Specify the band index number where ToolBar should be located withing the band of ToolBarTray /// ///public int BandIndex { get { return (int) GetValue(BandIndexProperty); } set { SetValue(BandIndexProperty, value); } } #endregion BandIndex #region IsOverflowOpen /// /// DependencyProperty for IsOverflowOpen /// public static readonly DependencyProperty IsOverflowOpenProperty = DependencyProperty.Register( "IsOverflowOpen", typeof(bool), typeof(ToolBar), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnOverflowOpenChanged), new CoerceValueCallback(CoerceIsOverflowOpen))); ////// Whether or not the "popup" for this control is currently open /// [Bindable(true), Browsable(false), Category("Appearance")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool IsOverflowOpen { get { return (bool) GetValue(IsOverflowOpenProperty); } set { SetValue(IsOverflowOpenProperty, BooleanBoxes.Box(value)); } } private static object CoerceIsOverflowOpen(DependencyObject d, object value) { if ((bool)value) { ToolBar tb = (ToolBar)d; if (!tb.IsLoaded) { tb.RegisterToOpenOnLoad(); return BooleanBoxes.FalseBox; } } return value; } private static object CoerceToolTipIsEnabled(DependencyObject d, object value) { ToolBar tb = (ToolBar) d; return tb.IsOverflowOpen ? BooleanBoxes.FalseBox : value; } private void RegisterToOpenOnLoad() { Loaded += new RoutedEventHandler(OpenOnLoad); } private void OpenOnLoad(object sender, RoutedEventArgs e) { // Open overflow after toolbar has rendered (Loaded is fired before 1st render) Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(delegate(object param) { CoerceValue(IsOverflowOpenProperty); return null; }), null); } private static void OnOverflowOpenChanged(DependencyObject element, DependencyPropertyChangedEventArgs e) { ToolBar toolBar = (ToolBar) element; if ((bool) e.NewValue) { // When the drop down opens, take capture Mouse.Capture(toolBar, CaptureMode.SubTree); toolBar.SetFocusOnToolBarOverflowPanel(); } else { // If focus is still within the ToolBarOverflowPanel, make sure we the focus is restored to the main focus scope ToolBarOverflowPanel overflow = toolBar.ToolBarOverflowPanel; if (overflow != null && overflow.IsKeyboardFocusWithin) { Keyboard.Focus(null); } if (Mouse.Captured == toolBar) { Mouse.Capture(null); } } toolBar.CoerceValue(ToolTipService.IsEnabledProperty); } private void SetFocusOnToolBarOverflowPanel() { Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(delegate(object param) { if (ToolBarOverflowPanel != null) { // If the overflow is opened by keyboard - focus the first item // otherwise - set focus on the panel itself if (KeyboardNavigation.IsKeyboardMostRecentInputDevice()) { ToolBarOverflowPanel.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); } else { ToolBarOverflowPanel.Focus(); } } return null; }), null); } #endregion IsOverflowOpen #region HasOverflowItems ////// The key needed set a read-only property. /// internal static readonly DependencyPropertyKey HasOverflowItemsPropertyKey = DependencyProperty.RegisterReadOnly( "HasOverflowItems", typeof(bool), typeof(ToolBar), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); ////// The DependencyProperty for the HasOverflowItems property. /// Flags: None /// Default Value: false /// public static readonly DependencyProperty HasOverflowItemsProperty = HasOverflowItemsPropertyKey.DependencyProperty; ////// Whether we have overflow items /// public bool HasOverflowItems { get { return (bool) GetValue(HasOverflowItemsProperty); } } #endregion HasOverflowItems #region IsOverflowItem ////// The key needed set a read-only property. /// Attached property to indicate if the item is placed in the overflow panel /// internal static readonly DependencyPropertyKey IsOverflowItemPropertyKey = DependencyProperty.RegisterAttachedReadOnly( "IsOverflowItem", typeof(bool), typeof(ToolBar), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); ////// The DependencyProperty for the IsOverflowItem property. /// Flags: None /// Default Value: false /// public static readonly DependencyProperty IsOverflowItemProperty = IsOverflowItemPropertyKey.DependencyProperty; ////// Writes the attached property IsOverflowItem to the given element. /// /// The element to which to write the attached property. /// The property value to set internal static void SetIsOverflowItem(DependencyObject element, object value) { element.SetValue(IsOverflowItemPropertyKey, value); } ////// Reads the attached property IsOverflowItem from the given element. /// /// The element from which to read the attached property. ///The property's value. public static bool GetIsOverflowItem(DependencyObject element) { if (element == null) { throw new ArgumentNullException("element"); } return (bool)element.GetValue(IsOverflowItemProperty); } #endregion #region OverflowMode ////// Attached property to indicate if the item should be placed in the overflow panel /// public static readonly DependencyProperty OverflowModeProperty = DependencyProperty.RegisterAttached( "OverflowMode", typeof(OverflowMode), typeof(ToolBar), new FrameworkPropertyMetadata( OverflowMode.AsNeeded, new PropertyChangedCallback(OnOverflowModeChanged)), new ValidateValueCallback(IsValidOverflowMode)); private static void OnOverflowModeChanged(DependencyObject element, DependencyPropertyChangedEventArgs e) { // When OverflowMode changes on a child container of a ToolBar, // invalidate layout so that the child can be placed in the correct // location (in the main bar or the overflow menu). ToolBar toolBar = ItemsControl.ItemsControlFromItemContainer(element) as ToolBar; if (toolBar != null) { toolBar.InvalidateLayout(); } } private void InvalidateLayout() { // Reset the calculated min and max size _minLength = 0.0; _maxLength = 0.0; // Min and max sizes are calculated in ToolBar.MeasureOverride InvalidateMeasure(); ToolBarPanel toolBarPanel = this.ToolBarPanel; if (toolBarPanel != null) { // Whether elements are in the overflow or not is decided // in ToolBarPanel.MeasureOverride. toolBarPanel.InvalidateMeasure(); } } private static bool IsValidOverflowMode(object o) { OverflowMode value = (OverflowMode)o; return value == OverflowMode.AsNeeded || value == OverflowMode.Always || value == OverflowMode.Never; } ////// Writes the attached property OverflowMode to the given element. /// /// The element to which to write the attached property. /// The property value to set public static void SetOverflowMode(DependencyObject element, OverflowMode mode) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(OverflowModeProperty, mode); } ////// Reads the attached property OverflowMode from the given element. /// /// The element from which to read the attached property. ///The property's value. [AttachedPropertyBrowsableForChildren(IncludeDescendants = true)] public static OverflowMode GetOverflowMode(DependencyObject element) { if (element == null) { throw new ArgumentNullException("element"); } return (OverflowMode)element.GetValue(OverflowModeProperty); } #endregion #endregion Properties #region Override methods ////// Creates AutomationPeer ( protected override AutomationPeer OnCreateAutomationPeer() { return new ToolBarAutomationPeer(this); } ///) /// /// Prepare the element to display the item. This may involve /// applying styles, setting bindings, etc. /// protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { base.PrepareContainerForItemOverride(element, item); // For certain known types, automatically change their default style // to point to a ToolBar version. FrameworkElement fe = element as FrameworkElement; if (fe != null) { Type feType = fe.GetType(); ResourceKey resourceKey = null; if (feType == typeof(Button)) resourceKey = ButtonStyleKey; else if (feType == typeof(ToggleButton)) resourceKey = ToggleButtonStyleKey; else if (feType == typeof(Separator)) resourceKey = SeparatorStyleKey; else if (feType == typeof(CheckBox)) resourceKey = CheckBoxStyleKey; else if (feType == typeof(RadioButton)) resourceKey = RadioButtonStyleKey; else if (feType == typeof(ComboBox)) resourceKey = ComboBoxStyleKey; else if (feType == typeof(TextBox)) resourceKey = TextBoxStyleKey; else if (feType == typeof(Menu)) resourceKey = MenuStyleKey; if (resourceKey != null) { bool hasModifiers; BaseValueSourceInternal vs = fe.GetValueSource(StyleProperty, null, out hasModifiers); if (vs <= BaseValueSourceInternal.ImplicitReference) fe.SetResourceReference(StyleProperty, resourceKey); fe.DefaultStyleKey = resourceKey; } } } internal override void OnTemplateChangedInternal(FrameworkTemplate oldTemplate, FrameworkTemplate newTemplate) { // Invalidate template references _toolBarPanel = null; _toolBarOverflowPanel = null; base.OnTemplateChangedInternal(oldTemplate, newTemplate); } ////// This method is invoked when the Items property changes. /// protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) { // When items change, invalidate layout so that the decision // regarding which items are in the overflow menu can be re-done. InvalidateLayout(); base.OnItemsChanged(e); } ////// Measure the content and store the desired size of the content /// /// ///protected override Size MeasureOverride(Size constraint) { // Perform a normal layout Size desiredSize = base.MeasureOverride(constraint); // // MinLength and MaxLength are used by ToolBarTray to determine // its layout. ToolBarPanel will calculate its version of these values. // ToolBar needs to add on the space used up by elements around the ToolBarPanel. // // Note: This calculation is not 100% accurate. If a scale transform is applied // within the template of the ToolBar (between the ToolBar and the ToolBarPanel), // then the coordinate spaces will not match and the values will be wrong. // // Note: If a ToolBarPanel is not contained within the ToolBar's template, // then these values will always be zero, and ToolBarTray will not layout correctly. // ToolBarPanel toolBarPanel = ToolBarPanel; if (toolBarPanel != null) { // Calculate the extra length from the extra space allocated between the ToolBar and the ToolBarPanel. double extraLength; Thickness margin = toolBarPanel.Margin; if (toolBarPanel.Orientation == Orientation.Horizontal) { extraLength = Math.Max(0.0, desiredSize.Width - toolBarPanel.DesiredSize.Width + margin.Left + margin.Right); } else { extraLength = Math.Max(0.0, desiredSize.Height - toolBarPanel.DesiredSize.Height + margin.Top + margin.Bottom); } // Add the calculated extra length to the lengths provided by ToolBarPanel _minLength = toolBarPanel.MinLength + extraLength; _maxLength = toolBarPanel.MaxLength + extraLength; } return desiredSize; } /// /// Called when this element loses mouse capture. /// /// protected override void OnLostMouseCapture(MouseEventArgs e) { base.OnLostMouseCapture(e); // ToolBar has a capture when its overflow panel is open // close the overflow panel is case capture is set to null if (Mouse.Captured == null) { Close(); } } #endregion Override methods #region Private implementation ////// Gets reference to ToolBar's ToolBarPanel element. /// internal ToolBarPanel ToolBarPanel { get { if (_toolBarPanel == null) _toolBarPanel = FindToolBarPanel(); return _toolBarPanel; } } private ToolBarPanel FindToolBarPanel() { DependencyObject child = GetTemplateChild(ToolBarPanelTemplateName); ToolBarPanel toolBarPanel = child as ToolBarPanel; if (child != null && toolBarPanel == null) throw new NotSupportedException(SR.Get(SRID.ToolBar_InvalidStyle_ToolBarPanel, child.GetType())); return toolBarPanel; } ////// Gets reference to ToolBar's ToolBarOverflowPanel element. /// internal ToolBarOverflowPanel ToolBarOverflowPanel { get { if (_toolBarOverflowPanel == null) _toolBarOverflowPanel = FindToolBarOverflowPanel(); return _toolBarOverflowPanel; } } private ToolBarOverflowPanel FindToolBarOverflowPanel() { DependencyObject child = GetTemplateChild(ToolBarOverflowPanelTemplateName); ToolBarOverflowPanel toolBarOverflowPanel = child as ToolBarOverflowPanel; if (child != null && toolBarOverflowPanel == null) throw new NotSupportedException(SR.Get(SRID.ToolBar_InvalidStyle_ToolBarOverflowPanel, child.GetType())); return toolBarOverflowPanel; } ////// This is the method that responds to the KeyDown event. /// /// protected override void OnKeyDown(KeyEventArgs e) { UIElement newFocusElement = null; UIElement currentFocusElement = e.Source as UIElement; if (currentFocusElement != null && ItemsControl.ItemsControlFromItemContainer(currentFocusElement) == this) { // itemsHost should be either ToolBarPanel or ToolBarOverflowPanel Panel itemsHost = VisualTreeHelper.GetParent(currentFocusElement) as Panel; if (itemsHost != null) { switch (e.Key) { // itemsHost.Children.Count is greater than zero because itemsHost is visual parent of currentFocusElement case Key.Home: newFocusElement = VisualTreeHelper.GetChild(itemsHost, 0) as UIElement; break; case Key.End: newFocusElement = VisualTreeHelper.GetChild(itemsHost, VisualTreeHelper.GetChildrenCount(itemsHost)-1) as UIElement; break; case Key.Escape: { // If focus is within ToolBarOverflowPanel - move focus the the toggle button ToolBarOverflowPanel overflow = ToolBarOverflowPanel; if (overflow != null && overflow.IsKeyboardFocusWithin) { MoveFocus(new TraversalRequest(FocusNavigationDirection.Last)); } else { Keyboard.Focus(null); } // Close the overflow the Esc is pressed Close(); } break; } if (newFocusElement != null) { if (newFocusElement.Focus()) e.Handled = true; } } } if (!e.Handled) base.OnKeyDown(e); } private static void OnMouseButtonDown(object sender, MouseButtonEventArgs e) { ToolBar toolBar = (ToolBar)sender; // Close the overflow for all unhandled mousedown in ToolBar if (!e.Handled) { toolBar.Close(); e.Handled = true; } } // ButtonBase.Click class handler // When we get a click event from toolbar item - close the overflow panel private static void _OnClick(object e, RoutedEventArgs args) { ToolBar toolBar = (ToolBar)e; ButtonBase bb = args.OriginalSource as ButtonBase; if (toolBar.IsOverflowOpen && bb != null && bb.Parent == toolBar) toolBar.Close(); } internal override void OnAncestorChanged() { // Orientation depends on the logical parent -- so invalidate it when that changes CoerceValue(OrientationProperty); } private void Close() { SetCurrentValueInternal(IsOverflowOpenProperty, BooleanBoxes.FalseBox); } private ToolBarTray ToolBarTray { get { return Parent as ToolBarTray; } } internal double MinLength { get { return _minLength; } } internal double MaxLength { get { return _maxLength; } } #endregion Private implementation #region private data private ToolBarPanel _toolBarPanel; private ToolBarOverflowPanel _toolBarOverflowPanel; private const string ToolBarPanelTemplateName = "PART_ToolBarPanel"; private const string ToolBarOverflowPanelTemplateName = "PART_ToolBarOverflowPanel"; private double _minLength = 0d; private double _maxLength = 0d; #endregion private data #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 #region ItemsStyleKey ////// Resource Key for the ButtonStyle /// public static ResourceKey ButtonStyleKey { get { return SystemResourceKey.ToolBarButtonStyleKey; } } ////// Resource Key for the ToggleButtonStyle /// public static ResourceKey ToggleButtonStyleKey { get { return SystemResourceKey.ToolBarToggleButtonStyleKey; } } ////// Resource Key for the SeparatorStyle /// public static ResourceKey SeparatorStyleKey { get { return SystemResourceKey.ToolBarSeparatorStyleKey; } } ////// Resource Key for the CheckBoxStyle /// public static ResourceKey CheckBoxStyleKey { get { return SystemResourceKey.ToolBarCheckBoxStyleKey; } } ////// Resource Key for the RadioButtonStyle /// public static ResourceKey RadioButtonStyleKey { get { return SystemResourceKey.ToolBarRadioButtonStyleKey; } } ////// Resource Key for the ComboBoxStyle /// public static ResourceKey ComboBoxStyleKey { get { return SystemResourceKey.ToolBarComboBoxStyleKey; } } ////// Resource Key for the TextBoxStyle /// public static ResourceKey TextBoxStyleKey { get { return SystemResourceKey.ToolBarTextBoxStyleKey; } } ////// Resource Key for the MenuStyle /// public static ResourceKey MenuStyleKey { get { return SystemResourceKey.ToolBarMenuStyleKey; } } #endregion ItemsStyleKey } } // 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; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Windows.Threading; using System.Windows; using System.Windows.Automation; using System.Windows.Automation.Peers; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using System.Windows.Markup; using System.Windows.Shapes; using MS.Utility; using MS.Internal.KnownBoxes; namespace System.Windows.Controls { #region public enum types ////// Defines how we place the toolbar items /// public enum OverflowMode { ////// specifies that the item moves between the main and the overflow panels as space permits /// AsNeeded, ////// specifies that the item is permanently placed in the overflow panel /// Always, ////// specifies that the item is never allowed to overflow /// Never // NOTE: if you add or remove any values in this enum, be sure to update ToolBar.IsValidOverflowMode() } #endregion public enum types ////// ToolBar provides an overflow mechanism which places any items that doesnt fit naturally /// fit within a size-constrained ToolBar into a special overflow area. /// Also, ToolBars have a tight relationship with the related ToolBarTray control. /// [TemplatePart(Name = "PART_ToolBarPanel", Type = typeof(ToolBarPanel))] [TemplatePart(Name = "PART_ToolBarOverflowPanel", Type = typeof(ToolBarOverflowPanel))] public class ToolBar : HeaderedItemsControl { #region Constructors static ToolBar() { // Disable tooltips on toolbar when the overflow is open ToolTipService.IsEnabledProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CoerceToolTipIsEnabled))); DefaultStyleKeyProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(typeof(ToolBar))); _dType = DependencyObjectType.FromSystemTypeInternal(typeof(ToolBar)); IsTabStopProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(MS.Internal.KnownBoxes.BooleanBoxes.FalseBox)); FocusableProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(MS.Internal.KnownBoxes.BooleanBoxes.FalseBox)); KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle)); KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle)); KeyboardNavigation.ControlTabNavigationProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once)); FocusManager.IsFocusScopeProperty.OverrideMetadata(typeof(ToolBar), new FrameworkPropertyMetadata(BooleanBoxes.TrueBox)); EventManager.RegisterClassHandler(typeof(ToolBar), Mouse.MouseDownEvent, new MouseButtonEventHandler(OnMouseButtonDown), true); EventManager.RegisterClassHandler(typeof(ToolBar), ButtonBase.ClickEvent, new RoutedEventHandler(_OnClick)); } ////// Default ToolBar constructor /// ////// Automatic determination of current Dispatcher. Use alternative constructor /// that accepts a Dispatcher for best performance. /// public ToolBar() : base() { } #endregion #region Properties #region Orientation ////// Property key for OrientationProperty. /// private static readonly DependencyPropertyKey OrientationPropertyKey = DependencyProperty.RegisterAttachedReadOnly( "Orientation", typeof(Orientation), typeof(ToolBar), new FrameworkPropertyMetadata( Orientation.Horizontal, null, new CoerceValueCallback(CoerceOrientation))); ////// Specifies the orientation (horizontal or vertical) of the flow /// public static readonly DependencyProperty OrientationProperty = OrientationPropertyKey.DependencyProperty; private static object CoerceOrientation(DependencyObject d, object value) { ToolBarTray toolBarTray = ((ToolBar) d).ToolBarTray; return (toolBarTray != null) ? toolBarTray.Orientation : value; } ////// Specifies the orientation of the ToolBar. This read-only property get its value from the ToolBarTray parent /// public Orientation Orientation { get { return (Orientation) GetValue(OrientationProperty); } } #endregion Orientation #region Band ////// Specify the band number where ToolBar should be located withing the ToolBarTray /// public static readonly DependencyProperty BandProperty = DependencyProperty.Register( "Band", typeof(int), typeof(ToolBar), new FrameworkPropertyMetadata( 0, FrameworkPropertyMetadataOptions.AffectsParentMeasure)); ////// Specify the band number where ToolBar should be located withing the ToolBarTray /// ///public int Band { get { return (int) GetValue(BandProperty); } set { SetValue(BandProperty, value); } } #endregion Band #region BandIndex /// /// Specify the band index number where ToolBar should be located within the band of ToolBarTray /// public static readonly DependencyProperty BandIndexProperty = DependencyProperty.Register( "BandIndex", typeof(int), typeof(ToolBar), new FrameworkPropertyMetadata( 0, FrameworkPropertyMetadataOptions.AffectsParentMeasure)); ////// Specify the band index number where ToolBar should be located withing the band of ToolBarTray /// ///public int BandIndex { get { return (int) GetValue(BandIndexProperty); } set { SetValue(BandIndexProperty, value); } } #endregion BandIndex #region IsOverflowOpen /// /// DependencyProperty for IsOverflowOpen /// public static readonly DependencyProperty IsOverflowOpenProperty = DependencyProperty.Register( "IsOverflowOpen", typeof(bool), typeof(ToolBar), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnOverflowOpenChanged), new CoerceValueCallback(CoerceIsOverflowOpen))); ////// Whether or not the "popup" for this control is currently open /// [Bindable(true), Browsable(false), Category("Appearance")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool IsOverflowOpen { get { return (bool) GetValue(IsOverflowOpenProperty); } set { SetValue(IsOverflowOpenProperty, BooleanBoxes.Box(value)); } } private static object CoerceIsOverflowOpen(DependencyObject d, object value) { if ((bool)value) { ToolBar tb = (ToolBar)d; if (!tb.IsLoaded) { tb.RegisterToOpenOnLoad(); return BooleanBoxes.FalseBox; } } return value; } private static object CoerceToolTipIsEnabled(DependencyObject d, object value) { ToolBar tb = (ToolBar) d; return tb.IsOverflowOpen ? BooleanBoxes.FalseBox : value; } private void RegisterToOpenOnLoad() { Loaded += new RoutedEventHandler(OpenOnLoad); } private void OpenOnLoad(object sender, RoutedEventArgs e) { // Open overflow after toolbar has rendered (Loaded is fired before 1st render) Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(delegate(object param) { CoerceValue(IsOverflowOpenProperty); return null; }), null); } private static void OnOverflowOpenChanged(DependencyObject element, DependencyPropertyChangedEventArgs e) { ToolBar toolBar = (ToolBar) element; if ((bool) e.NewValue) { // When the drop down opens, take capture Mouse.Capture(toolBar, CaptureMode.SubTree); toolBar.SetFocusOnToolBarOverflowPanel(); } else { // If focus is still within the ToolBarOverflowPanel, make sure we the focus is restored to the main focus scope ToolBarOverflowPanel overflow = toolBar.ToolBarOverflowPanel; if (overflow != null && overflow.IsKeyboardFocusWithin) { Keyboard.Focus(null); } if (Mouse.Captured == toolBar) { Mouse.Capture(null); } } toolBar.CoerceValue(ToolTipService.IsEnabledProperty); } private void SetFocusOnToolBarOverflowPanel() { Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(delegate(object param) { if (ToolBarOverflowPanel != null) { // If the overflow is opened by keyboard - focus the first item // otherwise - set focus on the panel itself if (KeyboardNavigation.IsKeyboardMostRecentInputDevice()) { ToolBarOverflowPanel.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); } else { ToolBarOverflowPanel.Focus(); } } return null; }), null); } #endregion IsOverflowOpen #region HasOverflowItems ////// The key needed set a read-only property. /// internal static readonly DependencyPropertyKey HasOverflowItemsPropertyKey = DependencyProperty.RegisterReadOnly( "HasOverflowItems", typeof(bool), typeof(ToolBar), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); ////// The DependencyProperty for the HasOverflowItems property. /// Flags: None /// Default Value: false /// public static readonly DependencyProperty HasOverflowItemsProperty = HasOverflowItemsPropertyKey.DependencyProperty; ////// Whether we have overflow items /// public bool HasOverflowItems { get { return (bool) GetValue(HasOverflowItemsProperty); } } #endregion HasOverflowItems #region IsOverflowItem ////// The key needed set a read-only property. /// Attached property to indicate if the item is placed in the overflow panel /// internal static readonly DependencyPropertyKey IsOverflowItemPropertyKey = DependencyProperty.RegisterAttachedReadOnly( "IsOverflowItem", typeof(bool), typeof(ToolBar), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); ////// The DependencyProperty for the IsOverflowItem property. /// Flags: None /// Default Value: false /// public static readonly DependencyProperty IsOverflowItemProperty = IsOverflowItemPropertyKey.DependencyProperty; ////// Writes the attached property IsOverflowItem to the given element. /// /// The element to which to write the attached property. /// The property value to set internal static void SetIsOverflowItem(DependencyObject element, object value) { element.SetValue(IsOverflowItemPropertyKey, value); } ////// Reads the attached property IsOverflowItem from the given element. /// /// The element from which to read the attached property. ///The property's value. public static bool GetIsOverflowItem(DependencyObject element) { if (element == null) { throw new ArgumentNullException("element"); } return (bool)element.GetValue(IsOverflowItemProperty); } #endregion #region OverflowMode ////// Attached property to indicate if the item should be placed in the overflow panel /// public static readonly DependencyProperty OverflowModeProperty = DependencyProperty.RegisterAttached( "OverflowMode", typeof(OverflowMode), typeof(ToolBar), new FrameworkPropertyMetadata( OverflowMode.AsNeeded, new PropertyChangedCallback(OnOverflowModeChanged)), new ValidateValueCallback(IsValidOverflowMode)); private static void OnOverflowModeChanged(DependencyObject element, DependencyPropertyChangedEventArgs e) { // When OverflowMode changes on a child container of a ToolBar, // invalidate layout so that the child can be placed in the correct // location (in the main bar or the overflow menu). ToolBar toolBar = ItemsControl.ItemsControlFromItemContainer(element) as ToolBar; if (toolBar != null) { toolBar.InvalidateLayout(); } } private void InvalidateLayout() { // Reset the calculated min and max size _minLength = 0.0; _maxLength = 0.0; // Min and max sizes are calculated in ToolBar.MeasureOverride InvalidateMeasure(); ToolBarPanel toolBarPanel = this.ToolBarPanel; if (toolBarPanel != null) { // Whether elements are in the overflow or not is decided // in ToolBarPanel.MeasureOverride. toolBarPanel.InvalidateMeasure(); } } private static bool IsValidOverflowMode(object o) { OverflowMode value = (OverflowMode)o; return value == OverflowMode.AsNeeded || value == OverflowMode.Always || value == OverflowMode.Never; } ////// Writes the attached property OverflowMode to the given element. /// /// The element to which to write the attached property. /// The property value to set public static void SetOverflowMode(DependencyObject element, OverflowMode mode) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(OverflowModeProperty, mode); } ////// Reads the attached property OverflowMode from the given element. /// /// The element from which to read the attached property. ///The property's value. [AttachedPropertyBrowsableForChildren(IncludeDescendants = true)] public static OverflowMode GetOverflowMode(DependencyObject element) { if (element == null) { throw new ArgumentNullException("element"); } return (OverflowMode)element.GetValue(OverflowModeProperty); } #endregion #endregion Properties #region Override methods ////// Creates AutomationPeer ( protected override AutomationPeer OnCreateAutomationPeer() { return new ToolBarAutomationPeer(this); } ///) /// /// Prepare the element to display the item. This may involve /// applying styles, setting bindings, etc. /// protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { base.PrepareContainerForItemOverride(element, item); // For certain known types, automatically change their default style // to point to a ToolBar version. FrameworkElement fe = element as FrameworkElement; if (fe != null) { Type feType = fe.GetType(); ResourceKey resourceKey = null; if (feType == typeof(Button)) resourceKey = ButtonStyleKey; else if (feType == typeof(ToggleButton)) resourceKey = ToggleButtonStyleKey; else if (feType == typeof(Separator)) resourceKey = SeparatorStyleKey; else if (feType == typeof(CheckBox)) resourceKey = CheckBoxStyleKey; else if (feType == typeof(RadioButton)) resourceKey = RadioButtonStyleKey; else if (feType == typeof(ComboBox)) resourceKey = ComboBoxStyleKey; else if (feType == typeof(TextBox)) resourceKey = TextBoxStyleKey; else if (feType == typeof(Menu)) resourceKey = MenuStyleKey; if (resourceKey != null) { bool hasModifiers; BaseValueSourceInternal vs = fe.GetValueSource(StyleProperty, null, out hasModifiers); if (vs <= BaseValueSourceInternal.ImplicitReference) fe.SetResourceReference(StyleProperty, resourceKey); fe.DefaultStyleKey = resourceKey; } } } internal override void OnTemplateChangedInternal(FrameworkTemplate oldTemplate, FrameworkTemplate newTemplate) { // Invalidate template references _toolBarPanel = null; _toolBarOverflowPanel = null; base.OnTemplateChangedInternal(oldTemplate, newTemplate); } ////// This method is invoked when the Items property changes. /// protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) { // When items change, invalidate layout so that the decision // regarding which items are in the overflow menu can be re-done. InvalidateLayout(); base.OnItemsChanged(e); } ////// Measure the content and store the desired size of the content /// /// ///protected override Size MeasureOverride(Size constraint) { // Perform a normal layout Size desiredSize = base.MeasureOverride(constraint); // // MinLength and MaxLength are used by ToolBarTray to determine // its layout. ToolBarPanel will calculate its version of these values. // ToolBar needs to add on the space used up by elements around the ToolBarPanel. // // Note: This calculation is not 100% accurate. If a scale transform is applied // within the template of the ToolBar (between the ToolBar and the ToolBarPanel), // then the coordinate spaces will not match and the values will be wrong. // // Note: If a ToolBarPanel is not contained within the ToolBar's template, // then these values will always be zero, and ToolBarTray will not layout correctly. // ToolBarPanel toolBarPanel = ToolBarPanel; if (toolBarPanel != null) { // Calculate the extra length from the extra space allocated between the ToolBar and the ToolBarPanel. double extraLength; Thickness margin = toolBarPanel.Margin; if (toolBarPanel.Orientation == Orientation.Horizontal) { extraLength = Math.Max(0.0, desiredSize.Width - toolBarPanel.DesiredSize.Width + margin.Left + margin.Right); } else { extraLength = Math.Max(0.0, desiredSize.Height - toolBarPanel.DesiredSize.Height + margin.Top + margin.Bottom); } // Add the calculated extra length to the lengths provided by ToolBarPanel _minLength = toolBarPanel.MinLength + extraLength; _maxLength = toolBarPanel.MaxLength + extraLength; } return desiredSize; } /// /// Called when this element loses mouse capture. /// /// protected override void OnLostMouseCapture(MouseEventArgs e) { base.OnLostMouseCapture(e); // ToolBar has a capture when its overflow panel is open // close the overflow panel is case capture is set to null if (Mouse.Captured == null) { Close(); } } #endregion Override methods #region Private implementation ////// Gets reference to ToolBar's ToolBarPanel element. /// internal ToolBarPanel ToolBarPanel { get { if (_toolBarPanel == null) _toolBarPanel = FindToolBarPanel(); return _toolBarPanel; } } private ToolBarPanel FindToolBarPanel() { DependencyObject child = GetTemplateChild(ToolBarPanelTemplateName); ToolBarPanel toolBarPanel = child as ToolBarPanel; if (child != null && toolBarPanel == null) throw new NotSupportedException(SR.Get(SRID.ToolBar_InvalidStyle_ToolBarPanel, child.GetType())); return toolBarPanel; } ////// Gets reference to ToolBar's ToolBarOverflowPanel element. /// internal ToolBarOverflowPanel ToolBarOverflowPanel { get { if (_toolBarOverflowPanel == null) _toolBarOverflowPanel = FindToolBarOverflowPanel(); return _toolBarOverflowPanel; } } private ToolBarOverflowPanel FindToolBarOverflowPanel() { DependencyObject child = GetTemplateChild(ToolBarOverflowPanelTemplateName); ToolBarOverflowPanel toolBarOverflowPanel = child as ToolBarOverflowPanel; if (child != null && toolBarOverflowPanel == null) throw new NotSupportedException(SR.Get(SRID.ToolBar_InvalidStyle_ToolBarOverflowPanel, child.GetType())); return toolBarOverflowPanel; } ////// This is the method that responds to the KeyDown event. /// /// protected override void OnKeyDown(KeyEventArgs e) { UIElement newFocusElement = null; UIElement currentFocusElement = e.Source as UIElement; if (currentFocusElement != null && ItemsControl.ItemsControlFromItemContainer(currentFocusElement) == this) { // itemsHost should be either ToolBarPanel or ToolBarOverflowPanel Panel itemsHost = VisualTreeHelper.GetParent(currentFocusElement) as Panel; if (itemsHost != null) { switch (e.Key) { // itemsHost.Children.Count is greater than zero because itemsHost is visual parent of currentFocusElement case Key.Home: newFocusElement = VisualTreeHelper.GetChild(itemsHost, 0) as UIElement; break; case Key.End: newFocusElement = VisualTreeHelper.GetChild(itemsHost, VisualTreeHelper.GetChildrenCount(itemsHost)-1) as UIElement; break; case Key.Escape: { // If focus is within ToolBarOverflowPanel - move focus the the toggle button ToolBarOverflowPanel overflow = ToolBarOverflowPanel; if (overflow != null && overflow.IsKeyboardFocusWithin) { MoveFocus(new TraversalRequest(FocusNavigationDirection.Last)); } else { Keyboard.Focus(null); } // Close the overflow the Esc is pressed Close(); } break; } if (newFocusElement != null) { if (newFocusElement.Focus()) e.Handled = true; } } } if (!e.Handled) base.OnKeyDown(e); } private static void OnMouseButtonDown(object sender, MouseButtonEventArgs e) { ToolBar toolBar = (ToolBar)sender; // Close the overflow for all unhandled mousedown in ToolBar if (!e.Handled) { toolBar.Close(); e.Handled = true; } } // ButtonBase.Click class handler // When we get a click event from toolbar item - close the overflow panel private static void _OnClick(object e, RoutedEventArgs args) { ToolBar toolBar = (ToolBar)e; ButtonBase bb = args.OriginalSource as ButtonBase; if (toolBar.IsOverflowOpen && bb != null && bb.Parent == toolBar) toolBar.Close(); } internal override void OnAncestorChanged() { // Orientation depends on the logical parent -- so invalidate it when that changes CoerceValue(OrientationProperty); } private void Close() { SetCurrentValueInternal(IsOverflowOpenProperty, BooleanBoxes.FalseBox); } private ToolBarTray ToolBarTray { get { return Parent as ToolBarTray; } } internal double MinLength { get { return _minLength; } } internal double MaxLength { get { return _maxLength; } } #endregion Private implementation #region private data private ToolBarPanel _toolBarPanel; private ToolBarOverflowPanel _toolBarOverflowPanel; private const string ToolBarPanelTemplateName = "PART_ToolBarPanel"; private const string ToolBarOverflowPanelTemplateName = "PART_ToolBarOverflowPanel"; private double _minLength = 0d; private double _maxLength = 0d; #endregion private data #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 #region ItemsStyleKey ////// Resource Key for the ButtonStyle /// public static ResourceKey ButtonStyleKey { get { return SystemResourceKey.ToolBarButtonStyleKey; } } ////// Resource Key for the ToggleButtonStyle /// public static ResourceKey ToggleButtonStyleKey { get { return SystemResourceKey.ToolBarToggleButtonStyleKey; } } ////// Resource Key for the SeparatorStyle /// public static ResourceKey SeparatorStyleKey { get { return SystemResourceKey.ToolBarSeparatorStyleKey; } } ////// Resource Key for the CheckBoxStyle /// public static ResourceKey CheckBoxStyleKey { get { return SystemResourceKey.ToolBarCheckBoxStyleKey; } } ////// Resource Key for the RadioButtonStyle /// public static ResourceKey RadioButtonStyleKey { get { return SystemResourceKey.ToolBarRadioButtonStyleKey; } } ////// Resource Key for the ComboBoxStyle /// public static ResourceKey ComboBoxStyleKey { get { return SystemResourceKey.ToolBarComboBoxStyleKey; } } ////// Resource Key for the TextBoxStyle /// public static ResourceKey TextBoxStyleKey { get { return SystemResourceKey.ToolBarTextBoxStyleKey; } } ////// Resource Key for the MenuStyle /// public static ResourceKey MenuStyleKey { get { return SystemResourceKey.ToolBarMenuStyleKey; } } #endregion ItemsStyleKey } } // 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
- Schema.cs
- PropertyRecord.cs
- Cursors.cs
- Version.cs
- ObjectStateManager.cs
- ExpanderAutomationPeer.cs
- XmlSchemaAppInfo.cs
- LoginName.cs
- AutomationElementIdentifiers.cs
- RtType.cs
- SemanticResultValue.cs
- Converter.cs
- ReadOnlyNameValueCollection.cs
- TrustManagerMoreInformation.cs
- DesignerEventService.cs
- StyleBamlRecordReader.cs
- DbConnectionPoolIdentity.cs
- TimeSpanMinutesConverter.cs
- CreateRefExpr.cs
- BindingCollectionElement.cs
- HtmlInputControl.cs
- HttpAsyncResult.cs
- ReflectionUtil.cs
- StickyNoteHelper.cs
- GifBitmapEncoder.cs
- SqlMethods.cs
- WebAdminConfigurationHelper.cs
- DesignerAttribute.cs
- DataControlField.cs
- CharStorage.cs
- TypedColumnHandler.cs
- PresentationAppDomainManager.cs
- FrameworkElementAutomationPeer.cs
- Base64Stream.cs
- ScrollBar.cs
- SmiContext.cs
- EasingKeyFrames.cs
- AppendHelper.cs
- DbConnectionPoolGroup.cs
- NativeObjectSecurity.cs
- NativeRightsManagementAPIsStructures.cs
- VScrollBar.cs
- FixedSOMLineRanges.cs
- ResourceKey.cs
- ListCardsInFileRequest.cs
- MetaForeignKeyColumn.cs
- NewItemsContextMenuStrip.cs
- PathFigure.cs
- RoleManagerModule.cs
- SimpleWebHandlerParser.cs
- HttpPostedFile.cs
- UrlMappingsSection.cs
- Grant.cs
- RSAOAEPKeyExchangeDeformatter.cs
- FixedSOMImage.cs
- Graphics.cs
- EraserBehavior.cs
- CoTaskMemHandle.cs
- Baml6ConstructorInfo.cs
- SettingsPropertyNotFoundException.cs
- WorkflowMessageEventHandler.cs
- DoubleAnimationBase.cs
- ConnectionString.cs
- TableLayoutStyle.cs
- future.cs
- WindowsGraphicsCacheManager.cs
- FloatAverageAggregationOperator.cs
- PropertyValue.cs
- DbConnectionPoolGroup.cs
- OutputCacheModule.cs
- XsdValidatingReader.cs
- Keywords.cs
- LineProperties.cs
- ClientBuildManager.cs
- ListBoxItem.cs
- HttpCapabilitiesSectionHandler.cs
- ConnectionManagementElementCollection.cs
- WpfWebRequestHelper.cs
- TransformConverter.cs
- ObjectDataSourceFilteringEventArgs.cs
- TypeHelpers.cs
- ImageSourceValueSerializer.cs
- LifetimeServices.cs
- NullNotAllowedCollection.cs
- CodeTypeMemberCollection.cs
- FontStyles.cs
- SQLInt32Storage.cs
- DataGridViewTopLeftHeaderCell.cs
- RijndaelCryptoServiceProvider.cs
- TdsParser.cs
- ReadOnlyPropertyMetadata.cs
- AttachedPropertyBrowsableForTypeAttribute.cs
- Rect3D.cs
- _ConnectionGroup.cs
- Point.cs
- FileVersionInfo.cs
- UnknownWrapper.cs
- RegexGroup.cs
- NamespaceList.cs
- ChangeToolStripParentVerb.cs