コード例 #1
0
        protected override System.Collections.Generic.List <AutomationPeer> GetChildrenCore()
        {
            // If Ribbon is Collapsed, dont show anything in the UIA tree
            if (OwningRibbon.IsCollapsed)
            {
                return(null);
            }

            List <AutomationPeer> children = new List <AutomationPeer>();

            // Step1: Add QAT + Title + ContextualTabGroupHeaderItemsControl
            if (OwningRibbon.QuickAccessToolBar != null)
            {
                AutomationPeer peer = CreatePeerForElement(OwningRibbon.QuickAccessToolBar);
                if (peer != null)
                {
                    children.Add(peer);
                }
            }

            if (OwningRibbon.TitleHost != null)
            {
                AutomationPeer peer = CreatePeerForElement(OwningRibbon.TitleHost);
                if (peer == null)
                {
                    FrameworkElement titleHost = OwningRibbon.TitleHost as FrameworkElement;
                    if (titleHost != null)
                    {
                        peer = new RibbonTitleAutomationPeer(titleHost);
                    }
                    else
                    {
                        peer = new UIElementAutomationPeer(OwningRibbon.TitleHost);
                    }
                }
                children.Add(peer);
            }

            if (OwningRibbon.ContextualTabGroupItemsControl != null)
            {
                AutomationPeer peer = CreatePeerForElement(OwningRibbon.ContextualTabGroupItemsControl);
                if (peer != null)
                {
                    children.Add(peer);
                }
            }

            // Step2: Add ApplicationMenu
            if (OwningRibbon.ApplicationMenu != null)
            {
                AutomationPeer peer = CreatePeerForElement(OwningRibbon.ApplicationMenu);
                if (peer != null)
                {
                    children.Add(peer);
                }
            }

            // Step3: Refresh RibbonTabHeaders
            // RibbonTabHeaderItemsControl doesnt appear in the UIA Tree, but its children RibbonTabHeader appear as children of RibbonTab
            // We need to ensure that RibbonTabHeader peers are created and refreshed manually here
            if (OwningRibbon.RibbonTabHeaderItemsControl != null)
            {
#if RIBBON_IN_FRAMEWORK
                AutomationPeer peer = CreatePeerForElement(OwningRibbon.RibbonTabHeaderItemsControl);
                if (peer != null)
                {
                    peer.ForceEnsureChildren();
                }
#else
                // We are unable to use this commented piece of code because ForceEnsureChildren
                // is an internal method in .Net 4.0. The public alternative is to use
                // AutomationPeer.ResetChildrenCache. However this methods isn't appropriate to be
                // called during a GetChildrenCore call because it causes a recursive call to the
                // GetChildren call for the current AutomationPeer which is prohibited. For
                // illustration here's a callstack.

                // Exception:System.InvalidOperationException: Recursive call to Automation Peer API is not valid. at
                // System.Windows.Automation.Peers.AutomationPeer.GetChildren() at
                // System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent) at
                // System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent) at
                // System.Windows.Automation.Peers.AutomationPeer.ValidateConnected(AutomationPeer connectedPeer) at
                // MS.Internal.Automation.ElementProxy.StaticWrap(AutomationPeer peer, AutomationPeer referencePeer) at
                // System.Windows.Automation.Peers.AutomationPeer.UpdateChildrenInternal(Int32 invalidateLimit) at
                // System.Windows.Automation.Peers.ItemsControlAutomationPeer.UpdateChildren() at
                // Microsoft.Windows.Automation.Peers.RibbonAutomationPeer.GetChildrenCore() at

                // Also note that this code path is hit only when the UIA client is listening for
                // structure changed events. UI Spy for instance doesn't do this by default and
                // hence you will not automatically see the above crash it in that case. You need
                // to configure the events to include structure changed.

                // -----------------------------------------------------------------------------------------
                // AutomationPeer peer = CreatePeerForElement(OwningRibbon.RibbonTabHeaderItemsControl);
                // if (peer != null)
                // {
                //     peer.ForceEnsureChildren();
                // }
                // -----------------------------------------------------------------------------------------

                // The strategy to create a new instance of the AutomationPeer is a workaround to
                // the above limitation. It is important to create a new instance each time so
                // that we guarantee that the children are in fact updated. A GetChildren call on
                // a previously existing AutomationPeer will short circuit due to the _childrenValid
                // flag. Hence the creation of a new AutomationPeer object each time around. Note
                // that it is only this one AutomationPeer instanced that is created anew each time.
                // The Peers for the descendents are not recreated.

                AutomationPeer peer = new RibbonTabHeaderItemsControlAutomationPeer(OwningRibbon.RibbonTabHeaderItemsControl);
                peer.GetChildren();
#endif
            }

            // Step4: Add RibbonTabs
            List <AutomationPeer> ribbonTabs = base.GetChildrenCore();
            if (ribbonTabs != null && ribbonTabs.Count > 0)
            {
                children.AddRange(ribbonTabs);

                // This is required for the RibbonTabHeaderDataAutomationPeers to correctly
                // connect to the parent RibbonTabDataAutomationPeer
                for (int i = 0; i < ribbonTabs.Count; i++)
                {
#if RIBBON_IN_FRAMEWORK
                    ribbonTabs[i].ForceEnsureChildren();
#else
                    ribbonTabs[i].GetChildren();
#endif
                }
            }

            // Step5: Add HelpPane that appears next to TabPanel
            UIElement helpPaneHost = OwningRibbon.HelpPaneHost;
            if (helpPaneHost != null)
            {
                AutomationPeer peer = CreatePeerForElement(helpPaneHost);
                if (peer == null)
                {
                    FrameworkElement helpPaneHostFE = helpPaneHost as FrameworkElement;
                    if (helpPaneHostFE != null)
                    {
                        peer = new FrameworkElementAutomationPeer(helpPaneHostFE);
                    }
                    else
                    {
                        peer = new UIElementAutomationPeer(helpPaneHost);
                    }
                }
                children.Add(peer);
            }

            return(children);
        }