| File: System\Windows\Automation\Peers\MenuItemAutomationPeer.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Windows.Automation.Provider; using System.Windows.Controls; namespace System.Windows.Automation.Peers { /// public class MenuItemAutomationPeer : FrameworkElementAutomationPeer, IExpandCollapseProvider, IInvokeProvider, IToggleProvider { /// public MenuItemAutomationPeer(MenuItem owner): base(owner) { } /// protected override string GetClassNameCore() { return "MenuItem"; } /// protected override AutomationControlType GetAutomationControlTypeCore() { return AutomationControlType.MenuItem; } /// public override object GetPattern(PatternInterface patternInterface) { object result = null; MenuItem owner = (MenuItem)Owner; if (patternInterface == PatternInterface.ExpandCollapse) { MenuItemRole role = owner.Role; if ( (role == MenuItemRole.TopLevelHeader || role == MenuItemRole.SubmenuHeader) && owner.HasItems) { result = this; } } else if (patternInterface == PatternInterface.Toggle) { if (owner.IsCheckable) { result = this; } } else if (patternInterface == PatternInterface.Invoke) { MenuItemRole role = owner.Role; if ( (role == MenuItemRole.TopLevelItem || role == MenuItemRole.SubmenuItem) && !owner.HasItems) { result = this; } } else if (patternInterface == PatternInterface.SynchronizedInput) { result = base.GetPattern(patternInterface); } return result; } /// <summary> /// Gets the size of a set that contains this MenuItem. /// </summary> /// <remarks> /// If <see cref="AutomationProperties.PositionInSetProperty"/> hasn't been set /// this method will calculate the position of the MenuItem based on its parent ItemsControl, /// if the ItemsControl is grouping the position will be relative to the group containing this item. /// </remarks> /// <returns> /// The value of <see cref="AutomationProperties.PositionInSetProperty"/> if it has been set, or it's position relative to the parent ItemsControl or GroupItem. /// </returns> protected override int GetSizeOfSetCore() { int sizeOfSet = base.GetSizeOfSetCore(); if (sizeOfSet == AutomationProperties.AutomationSizeOfSetDefault) { MenuItem owner = (MenuItem)Owner; ItemsControl parent = ItemsControl.ItemsControlFromItemContainer(owner); sizeOfSet = ItemAutomationPeer.GetSizeOfSetFromItemsControl(parent, owner); foreach (var item in parent.Items) { if (item is Separator) { sizeOfSet -= 1; } } } return sizeOfSet; } /// <summary> /// Gets the position of a MenuItem contained in a set. /// </summary> /// <remarks> /// If this value has already been set by the developer, that value will be used for this property. If it hasn't, we find the position ourselves. /// </remarks> /// <returns> /// The position of a MenuItem that is contained in a set. /// </returns> protected override int GetPositionInSetCore() { int positionInSet = base.GetPositionInSetCore(); if (positionInSet == AutomationProperties.AutomationPositionInSetDefault) { MenuItem owner = (MenuItem)Owner; ItemsControl parent = ItemsControl.ItemsControlFromItemContainer(owner); positionInSet = ItemAutomationPeer.GetPositionInSetFromItemsControl(parent, owner); foreach (var item in parent.Items) { if (item == owner) { break; } if (item is Separator) { positionInSet -= 1; } } } return positionInSet; } /// protected override string GetAccessKeyCore() { string accessKey = base.GetAccessKeyCore(); if (!string.IsNullOrEmpty(accessKey)) { MenuItem menuItem = (MenuItem)Owner; MenuItemRole role = menuItem.Role; if (role == MenuItemRole.TopLevelHeader || role == MenuItemRole.TopLevelItem) { accessKey = $"Alt+{accessKey}"; } } return accessKey; } // MenuItem cannot rely on the base which gets the visal children because submenu items are part of // other visual tree under a Popup. // We return the list of items containers if they are currently visible // In case MenuItem is not expanded we return null /// protected override List<AutomationPeer> GetChildrenCore() { List<AutomationPeer> children = base.GetChildrenCore(); if (ExpandCollapseState.Expanded == ((IExpandCollapseProvider)this).ExpandCollapseState) { ItemsControl owner = (ItemsControl)Owner; ItemCollection items = owner.Items; if (items.Count > 0) { children = new List<AutomationPeer>(items.Count); for (int i = 0; i < items.Count; i++) { UIElement uiElement = owner.ItemContainerGenerator.ContainerFromIndex(i) as UIElement; if (uiElement != null) { AutomationPeer peer = UIElementAutomationPeer.FromElement(uiElement); if (peer == null) peer = UIElementAutomationPeer.CreatePeerForElement(uiElement); if( peer!= null) children.Add(peer); } } } } return children; } /// void IExpandCollapseProvider.Expand() { if(!IsEnabled()) throw new ElementNotEnabledException(); MenuItem owner = (MenuItem)Owner; MenuItemRole role = owner.Role; if ( (role != MenuItemRole.TopLevelHeader && role != MenuItemRole.SubmenuHeader) || !owner.HasItems) { throw new InvalidOperationException(SR.UIA_OperationCannotBePerformed); } owner.OpenMenu(); } /// void IExpandCollapseProvider.Collapse() { if(!IsEnabled()) throw new ElementNotEnabledException(); MenuItem owner = (MenuItem)Owner; MenuItemRole role = owner.Role; if ( (role != MenuItemRole.TopLevelHeader && role != MenuItemRole.SubmenuHeader) || !owner.HasItems) { throw new InvalidOperationException(SR.UIA_OperationCannotBePerformed); } owner.SetCurrentValueInternal(MenuItem.IsSubmenuOpenProperty, MS.Internal.KnownBoxes.BooleanBoxes.FalseBox); } /// ExpandCollapseState IExpandCollapseProvider.ExpandCollapseState { get { ExpandCollapseState result = ExpandCollapseState.Collapsed; MenuItem owner = (MenuItem)Owner; MenuItemRole role = owner.Role; if (role == MenuItemRole.TopLevelItem || role == MenuItemRole.SubmenuItem || !owner.HasItems) { result = ExpandCollapseState.LeafNode; } else if (owner.IsSubmenuOpen) { result = ExpandCollapseState.Expanded; } return result; } } /// void IInvokeProvider.Invoke() { if(!IsEnabled()) throw new ElementNotEnabledException(); MenuItem owner = (MenuItem)Owner; MenuItemRole role = owner.Role; if (role == MenuItemRole.TopLevelItem || role == MenuItemRole.SubmenuItem) { owner.ClickItem(); } else if (role == MenuItemRole.TopLevelHeader || role == MenuItemRole.SubmenuHeader) { owner.ClickHeader(); } } /// void IToggleProvider.Toggle() { if(!IsEnabled()) throw new ElementNotEnabledException(); MenuItem owner = (MenuItem)Owner; if (!owner.IsCheckable) { throw new InvalidOperationException(SR.UIA_OperationCannotBePerformed); } owner.SetCurrentValueInternal(MenuItem.IsCheckedProperty, MS.Internal.KnownBoxes.BooleanBoxes.Box(!owner.IsChecked)); } /// ToggleState IToggleProvider.ToggleState { get { MenuItem owner = (MenuItem)Owner; return owner.IsChecked ? ToggleState.On : ToggleState.Off; } } /// // BUG 1555137: Never inline, as we don't want to unnecessarily link the automation DLL [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] internal void RaiseExpandCollapseAutomationEvent(bool oldValue, bool newValue) { RaisePropertyChangedEvent( ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty, oldValue ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed, newValue ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed); } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] internal void RaiseToggleStatePropertyChangedEvent(bool oldValue, bool newValue) { RaisePropertyChangedEvent(TogglePatternIdentifiers.ToggleStateProperty, oldValue ? ConvertToToggleState(oldValue) : ConvertToToggleState(newValue), newValue ? ConvertToToggleState(oldValue) : ConvertToToggleState(newValue)); } private static ToggleState ConvertToToggleState(bool value) => value ? ToggleState.On : ToggleState.Off; // Return the base without the AccessKey character /// protected override string GetNameCore() { string result = base.GetNameCore(); if (!string.IsNullOrEmpty(result)) { MenuItem menuItem = (MenuItem)Owner; if (menuItem.Header is string) { return AccessText.RemoveAccessKeyMarker(result); } } return result; } } }