Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / ContextMenu.cs / 1305600 / ContextMenu.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using MS.Internal; using MS.Internal.KnownBoxes; using MS.Utility; using System.ComponentModel; using System.Diagnostics; using System.Windows.Threading; using System.Windows; #if OLD_AUTOMATION using System.Windows.Automation.Provider; #endif using System.Windows.Input; using System.Windows.Media; using System.Windows.Controls.Primitives; using System.Windows.Markup; using System.Windows.Shapes; using System.Security.Permissions; namespace System.Windows.Controls { ////// Control that defines a menu of choices for users to invoke. /// [DefaultEvent("Opened")] #if OLD_AUTOMATION [Automation(AccessibilityControlType = "Menu")] #endif public class ContextMenu : MenuBase { #region Constructors //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- static ContextMenu() { EventManager.RegisterClassHandler(typeof(ContextMenu), AccessKeyManager.AccessKeyPressedEvent, new AccessKeyPressedEventHandler(OnAccessKeyPressed)); DefaultStyleKeyProperty.OverrideMetadata(typeof(ContextMenu), new FrameworkPropertyMetadata(typeof(ContextMenu))); _dType = DependencyObjectType.FromSystemTypeInternal(typeof(ContextMenu)); IsTabStopProperty.OverrideMetadata(typeof(ContextMenu), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(ContextMenu), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle)); KeyboardNavigation.ControlTabNavigationProperty.OverrideMetadata(typeof(ContextMenu), new FrameworkPropertyMetadata(KeyboardNavigationMode.Contained)); KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(ContextMenu), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle)); // Disable the default focus visual for ContextMenu FocusVisualStyleProperty.OverrideMetadata(typeof(ContextMenu), new FrameworkPropertyMetadata((object)null /* default value */)); } ////// Default ContextMenu constructor /// ////// Automatic determination of current Dispatcher. Use alternative constructor /// that accepts a Dispatcher for best performance. /// public ContextMenu() : base() { Initialize(); } #endregion #region Public Properties //-------------------------------------------------------------------- // // Public Properties // //------------------------------------------------------------------- ////// The DependencyProperty for the HorizontalOffset property. /// public static readonly DependencyProperty HorizontalOffsetProperty = ContextMenuService.HorizontalOffsetProperty.AddOwner(typeof(ContextMenu), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CoerceHorizontalOffset))); private static object CoerceHorizontalOffset(DependencyObject d, object value) { return PopupControlService.CoerceProperty(d, value, ContextMenuService.HorizontalOffsetProperty); } ////// Get or set X offset of the ContextMenu /// [TypeConverter(typeof(LengthConverter))] [Bindable(true), Category("Layout")] public double HorizontalOffset { get { return (double) GetValue(HorizontalOffsetProperty); } set { SetValue(HorizontalOffsetProperty, value); } } ////// The DependencyProperty for the VerticalOffset property. /// public static readonly DependencyProperty VerticalOffsetProperty = ContextMenuService.VerticalOffsetProperty.AddOwner(typeof(ContextMenu), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CoerceVerticalOffset))); private static object CoerceVerticalOffset(DependencyObject d, object value) { return PopupControlService.CoerceProperty(d, value, ContextMenuService.VerticalOffsetProperty); } ////// Get or set Y offset of the ContextMenu /// [TypeConverter(typeof(LengthConverter))] [Bindable(true), Category("Layout")] public double VerticalOffset { get { return (double) GetValue(VerticalOffsetProperty); } set { SetValue(VerticalOffsetProperty, value); } } ////// DependencyProperty for IsOpen property /// public static readonly DependencyProperty IsOpenProperty = Popup.IsOpenProperty.AddOwner( typeof(ContextMenu), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnIsOpenChanged))); ////// Get or set IsOpen property of the ContextMenu /// [Bindable(true), Browsable(false), Category("Appearance")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool IsOpen { get { return (bool) GetValue(IsOpenProperty); } set { SetValue(IsOpenProperty, BooleanBoxes.Box(value)); } } private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ContextMenu ctrl = (ContextMenu) d; if ((bool) e.NewValue) { if (ctrl._parentPopup == null) { ctrl.HookupParentPopup(); } ctrl._parentPopup.Unloaded += new RoutedEventHandler(ctrl.OnPopupUnloaded); // Turn on keyboard cues in case ContextMenu was opened with the keyboard ctrl.SetValue(KeyboardNavigation.ShowKeyboardCuesProperty, KeyboardNavigation.IsKeyboardMostRecentInputDevice()); } else { ctrl.ClosingMenu(); } } ////// The DependencyProperty for the PlacementTarget property. /// public static readonly DependencyProperty PlacementTargetProperty = ContextMenuService.PlacementTargetProperty.AddOwner( typeof(ContextMenu), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CoercePlacementTarget))); private static object CoercePlacementTarget(DependencyObject d, object value) { return PopupControlService.CoerceProperty(d, value, ContextMenuService.PlacementTargetProperty); } ////// Get or set PlacementTarget property of the ContextMenu /// [Bindable(true), Category("Layout")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public UIElement PlacementTarget { get { return (UIElement) GetValue(PlacementTargetProperty); } set { SetValue(PlacementTargetProperty, value); } } ////// The DependencyProperty for the PlacementRectangle property. /// public static readonly DependencyProperty PlacementRectangleProperty = ContextMenuService.PlacementRectangleProperty.AddOwner(typeof(ContextMenu), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CoercePlacementRectangle))); private static object CoercePlacementRectangle(DependencyObject d, object value) { return PopupControlService.CoerceProperty(d, value, ContextMenuService.PlacementRectangleProperty); } ////// Get or set PlacementRectangle property of the ContextMenu /// [Bindable(true), Category("Layout")] public Rect PlacementRectangle { get { return (Rect) GetValue(PlacementRectangleProperty); } set { SetValue(PlacementRectangleProperty, value); } } ////// The DependencyProperty for the Placement property. /// public static readonly DependencyProperty PlacementProperty = ContextMenuService.PlacementProperty.AddOwner(typeof(ContextMenu), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CoercePlacement))); private static object CoercePlacement(DependencyObject d, object value) { return PopupControlService.CoerceProperty(d, value, ContextMenuService.PlacementProperty); } ////// Get or set Placement property of the ContextMenu /// [Bindable(true), Category("Layout")] public PlacementMode Placement { get { return (PlacementMode) GetValue(PlacementProperty); } set { SetValue(PlacementProperty, value); } } ////// The DependencyProperty for HasDropShadow /// public static readonly DependencyProperty HasDropShadowProperty = ContextMenuService.HasDropShadowProperty.AddOwner( typeof(ContextMenu), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CoerceHasDropShadow))); private static object CoerceHasDropShadow(DependencyObject d, object value) { ContextMenu cm = (ContextMenu)d; if (cm._parentPopup == null || !cm._parentPopup.AllowsTransparency || !SystemParameters.DropShadow) { return BooleanBoxes.FalseBox; } return PopupControlService.CoerceProperty(d, value, ContextMenuService.HasDropShadowProperty); } ////// Whether the control has a drop shadow. /// public bool HasDropShadow { get { return (bool)GetValue(HasDropShadowProperty); } set { SetValue(HasDropShadowProperty, value); } } ////// The DependencyProperty for the CustomPopupPlacementCallback property. /// Flags: None /// Default Value: null /// public static readonly DependencyProperty CustomPopupPlacementCallbackProperty = Popup.CustomPopupPlacementCallbackProperty.AddOwner(typeof(ContextMenu)); ////// Chooses the behavior of where the ContextMenu should be placed on screen. /// [Bindable(false), Category("Layout")] public CustomPopupPlacementCallback CustomPopupPlacementCallback { get { return (CustomPopupPlacementCallback) GetValue(CustomPopupPlacementCallbackProperty); } set { SetValue(CustomPopupPlacementCallbackProperty, value); } } ////// The DependencyProperty for the StaysOpen property. /// Indicates that, once opened, ContextMenu should stay open until IsOpenProperty changed to 'false'. /// Flags: None /// Default Value: false /// public static readonly DependencyProperty StaysOpenProperty = Popup.StaysOpenProperty.AddOwner(typeof(ContextMenu)); ////// Chooses the behavior of when the ContextMenu should automatically close. /// [Bindable(true), Category("Behavior")] public bool StaysOpen { get { return (bool) GetValue(StaysOpenProperty); } set { SetValue(StaysOpenProperty, value); } } #endregion #region Events ////// Opened event /// public static readonly RoutedEvent OpenedEvent = PopupControlService.ContextMenuOpenedEvent.AddOwner(typeof(ContextMenu)); ////// Event that fires when the popup opens. /// public event RoutedEventHandler Opened { add { AddHandler(OpenedEvent, value); } remove { RemoveHandler(OpenedEvent, value); } } ////// Called when the OpenedEvent fires. /// /// protected virtual void OnOpened(RoutedEventArgs e) { RaiseEvent(e); } ////// Closed event /// public static readonly RoutedEvent ClosedEvent = PopupControlService.ContextMenuClosedEvent.AddOwner(typeof(ContextMenu)); ////// Event that fires when the popup closes /// public event RoutedEventHandler Closed { add { AddHandler(ClosedEvent, value); } remove { RemoveHandler(ClosedEvent, value); } } ////// Called when the ClosedEvent fires. /// /// protected virtual void OnClosed(RoutedEventArgs e) { RaiseEvent(e); } #endregion //-------------------------------------------------------------------- // // Protected Methods // //-------------------------------------------------------------------- #region Protected Methods ////// Creates AutomationPeer ( protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() { return new System.Windows.Automation.Peers.ContextMenuAutomationPeer(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); MenuItem.PrepareMenuItem(element, item); } ////// If control has a scrollviewer in its style and has a custom keyboard scrolling behavior when HandlesScrolling should return true. /// Then ScrollViewer will not handle keyboard input and leave it up to the control. /// protected internal override bool HandlesScrolling { get { return true; } } ////// This is the method that responds to the KeyDown event. /// /// Event arguments protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (e.Handled || !IsOpen) { // Ignore if the event was already handled or if the menu closed. This might happen // if input events get queued up and one in the middle caused the menu to close. return; } Key key = e.Key; switch (key) { case Key.Down: if (CurrentSelection == null) { NavigateToStart(new ItemNavigateArgs(e.Device, Keyboard.Modifiers)); e.Handled = true; } break; case Key.Up: if (CurrentSelection == null) { NavigateToEnd(new ItemNavigateArgs(e.Device, Keyboard.Modifiers)); e.Handled = true; } break; } } ////// This is the method that responds to the KeyUp event. /// /// Event arguments protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e); if (!e.Handled && IsOpen && e.Key == Key.Apps) { KeyboardLeaveMenuMode(); e.Handled = true; } } #endregion #region Implementation private static readonly DependencyProperty InsideContextMenuProperty = MenuItem.InsideContextMenuProperty.AddOwner(typeof(ContextMenu), new FrameworkPropertyMetadata(BooleanBoxes.TrueBox, FrameworkPropertyMetadataOptions.Inherits)); //------------------------------------------------------------------- // // Implementation // //-------------------------------------------------------------------- private void Initialize() { // We have to set this locally in order for inheritance to work MenuItem.SetInsideContextMenuProperty(this, true); InternalMenuModeChanged += new EventHandler(OnIsMenuModeChanged); } private void HookupParentPopup() { Debug.Assert(_parentPopup == null, "_parentPopup should be null"); _parentPopup = new Popup(); _parentPopup.AllowsTransparency = true; // Coerce HasDropShadow property in case popup can't be transparent CoerceValue(HasDropShadowProperty); _parentPopup.DropOpposite = false; // Listening to the Opened and Closed events lets us guarantee that // the popup is actually opened when we perform those functions. _parentPopup.Opened += new EventHandler(OnPopupOpened); _parentPopup.Closed += new EventHandler(OnPopupClosed); _parentPopup.PopupCouldClose += new EventHandler(OnPopupCouldClose); _parentPopup.SetResourceReference(Popup.PopupAnimationProperty, SystemParameters.MenuPopupAnimationKey); // Hooks up the popup properties from this menu to the popup so that // setting them on this control will also set them on the popup. Popup.CreateRootPopup(_parentPopup, this); } private void OnPopupCouldClose(object sender, EventArgs e) { SetCurrentValueInternal(IsOpenProperty, BooleanBoxes.FalseBox); } private void OnPopupOpened(object source, EventArgs e) { if (CurrentSelection != null) { CurrentSelection = null; } IsMenuMode = true; // When we open, if the Left or Right buttons are pressed, MenuBase should not // dismiss when it sees the up for those buttons. if (Mouse.LeftButton == MouseButtonState.Pressed) { IgnoreNextLeftRelease = true; } if (Mouse.RightButton == MouseButtonState.Pressed) { IgnoreNextRightRelease = true; } OnOpened(new RoutedEventArgs(OpenedEvent, this)); } private void OnPopupClosed(object source, EventArgs e) { // Clear out any state we stored for this time around IgnoreNextLeftRelease = false; IgnoreNextRightRelease = false; IsMenuMode = false; OnClosed(new RoutedEventArgs(ClosedEvent, this)); } private void ClosingMenu() { if (_parentPopup != null) { _parentPopup.Unloaded -= new RoutedEventHandler(OnPopupUnloaded); // As the menu closes, we need the parent connection to be maintained // while we do things like release capture so that notifications // go up the tree correctly. Post this for later. Dispatcher.BeginInvoke(DispatcherPriority.Normal, (DispatcherOperationCallback)delegate(object arg) { ContextMenu cm = (ContextMenu)arg; if (!cm.IsOpen) // Check that the menu is still closed { // Prevent focus scoping from remembering the last focused element. // The next time the menu opens, we want to start clean. FocusManager.SetFocusedElement(cm, null); } return null; }, this); } } private void OnPopupUnloaded(object sender, RoutedEventArgs e) { // The tree that the ContextMenu is in is being torn down, close the menu. if (IsOpen) { // This will be called during a tree walk, closing the menu will cause a tree change, // so post for later. Dispatcher.BeginInvoke(DispatcherPriority.Send, (DispatcherOperationCallback)delegate(object arg) { ContextMenu cm = (ContextMenu)arg; if (cm.IsOpen) // Check that the menu is still open { cm.SetCurrentValueInternal(IsOpenProperty, BooleanBoxes.FalseBox); } return null; }, this); } } ////// Called when IsMenuMode changes on this class /// private void OnIsMenuModeChanged(object sender, EventArgs e) { // IsMenuMode changed from false to true if (IsMenuMode) { // Keep the previous focus if (Keyboard.FocusedElement != null) _weakRefToPreviousFocus = new WeakReference(Keyboard.FocusedElement); // Take focus so we get keyboard events. Focus(); } else // IsMenuMode changed from true to false { SetCurrentValueInternal(IsOpenProperty, BooleanBoxes.FalseBox); // Restore the previous focus if (_weakRefToPreviousFocus != null && _weakRefToPreviousFocus.IsAlive) (_weakRefToPreviousFocus.Target as IInputElement).Focus(); } } internal override bool IgnoreModelParentBuildRoute(RoutedEventArgs e) { // Context menus are logically connected to their host element. Generally, we don't // want input events to route out of the context menu. Consider the sitituation where // a TextBox has a ContextMenu. It is confusing for the text box to move the cursor // when I press the arrow keys while the context menu is being displayed. // // For now we only block keyboard events and ToolTip events. What about mouse & stylus events? // // Note: This will cause the route to not follow the logical link, but it will still // follow the visual link. At the time of writing this comment, the visual link // contained things like an adorner decorator. Eventually the visual ancestory lead // to a PopupRoot, which also has a logical link over to the Popup element. Since // the PopupRoot does not override this virtual, the route continues through its logical // link and ends up escaping into the larger logical tree anyways. // // The solution is that the PopupRoot element (on the top of this visual tree) will // defer back to this method to determine if it should route any further. // return (e is KeyEventArgs) || (e is FindToolTipEventArgs); } private static void OnAccessKeyPressed(object sender, AccessKeyPressedEventArgs e) { e.Scope = sender; e.Handled = true; } ////// Called when this element's visual parent changes /// /// protected internal override void OnVisualParentChanged(DependencyObject oldParent) { base.OnVisualParentChanged(oldParent); if (!Popup.IsRootedInPopup(_parentPopup, this)) { throw new InvalidOperationException(SR.Get(SRID.ElementMustBeInPopup, "ContextMenu")); } } internal override void OnAncestorChanged() { base.OnAncestorChanged(); if (!Popup.IsRootedInPopup(_parentPopup, this)) { throw new InvalidOperationException(SR.Get(SRID.ElementMustBeInPopup, "ContextMenu")); } } #endregion #region Private Fields private Popup _parentPopup; private WeakReference _weakRefToPreviousFocus; // Keep the previously focused element before CM to open #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
- SessionStateItemCollection.cs
- BrushMappingModeValidation.cs
- XmlSerializationReader.cs
- FontSource.cs
- PageCache.cs
- Interop.cs
- ContentWrapperAttribute.cs
- MetadataCache.cs
- util.cs
- ObjectDataSourceDisposingEventArgs.cs
- SingleBodyParameterMessageFormatter.cs
- ArrayListCollectionBase.cs
- Win32Exception.cs
- AmbientValueAttribute.cs
- DynamicDiscoveryDocument.cs
- SortableBindingList.cs
- TraceHwndHost.cs
- QueryHandler.cs
- RotateTransform.cs
- SplitterPanel.cs
- MDIWindowDialog.cs
- WizardForm.cs
- TransformCollection.cs
- dsa.cs
- IPEndPointCollection.cs
- ObjectDataSourceStatusEventArgs.cs
- XsdDataContractExporter.cs
- CachedRequestParams.cs
- SqlParameterizer.cs
- CqlBlock.cs
- InstanceData.cs
- InvokeAction.cs
- EntityReference.cs
- PeerNameRecord.cs
- Win32Native.cs
- Int16Storage.cs
- ExcludePathInfo.cs
- ParsedAttributeCollection.cs
- GridViewAutomationPeer.cs
- UrlPropertyAttribute.cs
- DataListItem.cs
- UrlMappingsModule.cs
- PageCatalogPartDesigner.cs
- ContentPresenter.cs
- OleDbReferenceCollection.cs
- ParameterCollection.cs
- SiteIdentityPermission.cs
- MailMessageEventArgs.cs
- DnsPermission.cs
- CodeTypeReference.cs
- TemplateControlCodeDomTreeGenerator.cs
- ResourceProperty.cs
- DownloadProgressEventArgs.cs
- DataGridCommandEventArgs.cs
- SqlConnectionPoolGroupProviderInfo.cs
- ComplexLine.cs
- SizeAnimation.cs
- followingsibling.cs
- TypeConverterHelper.cs
- ILGenerator.cs
- TypeElement.cs
- IsolatedStoragePermission.cs
- RegionData.cs
- XDeferredAxisSource.cs
- ServiceContractAttribute.cs
- PingOptions.cs
- ServiceMemoryGates.cs
- SHA256.cs
- DetailsViewUpdateEventArgs.cs
- FlowchartDesigner.Helpers.cs
- CompilerErrorCollection.cs
- EDesignUtil.cs
- DataControlFieldCell.cs
- CustomWebEventKey.cs
- Site.cs
- EnumerableRowCollectionExtensions.cs
- ConnectionConsumerAttribute.cs
- Vector3DCollection.cs
- _NativeSSPI.cs
- RightsManagementEncryptionTransform.cs
- MetadataCache.cs
- DataGridCellClipboardEventArgs.cs
- TouchFrameEventArgs.cs
- httpstaticobjectscollection.cs
- TypeSystem.cs
- DetailsViewUpdateEventArgs.cs
- Utilities.cs
- IRCollection.cs
- DataKeyArray.cs
- RequiredFieldValidator.cs
- BufferModesCollection.cs
- TextContainer.cs
- XmlWriterSettings.cs
- RectangleConverter.cs
- GatewayIPAddressInformationCollection.cs
- DefaultEventAttribute.cs
- RunWorkerCompletedEventArgs.cs
- DisposableCollectionWrapper.cs
- PeerNameRecord.cs
- PolyLineSegment.cs