// Selected TabItem content is located under the TabControl style visual tree /// protected override List<AutomationPeer> GetChildrenCore() { // Call the base in case we have children in the header List<AutomationPeer> headerChildren = base.GetChildrenCore(); // Only if the TabItem is selected we need to add its visual children TabItem tabItem = GetWrapper() as TabItem; if (tabItem != null && tabItem.IsSelected) { TabControl parentTabControl = ItemsControlAutomationPeer.Owner as TabControl; if (parentTabControl != null) { ContentPresenter contentHost = parentTabControl.SelectedContentPresenter; if (contentHost != null) { AutomationPeer contentHostPeer = new FrameworkElementAutomationPeer(contentHost); List<AutomationPeer> contentChildren = contentHostPeer.GetChildren(); if (contentChildren != null) { if (headerChildren == null) headerChildren = contentChildren; else headerChildren.AddRange(contentChildren); } } } } return headerChildren; }
protected override List<AutomationPeer> GetChildrenCore() { List<AutomationPeer> childrenCore = base.GetChildrenCore(); TabItem wrapper = Item as TabItem; if ((wrapper != null) && wrapper.IsSelected) { TabControl control = TabOwner; if (control == null) { return childrenCore; } ContentPresenter selectedContentPresenter = control.GetContentHost(control.TabStripPlacement); if (selectedContentPresenter == null) { return childrenCore; } List<AutomationPeer> children = new FrameworkElementAutomationPeer(selectedContentPresenter).GetChildren(); if (children == null) { return childrenCore; } if (childrenCore == null) { return children; } childrenCore.AddRange(children); } return childrenCore; }
internal static AutomationPeer CreatePeer(UIElement element) { AutomationPeer peer = UIElementAutomationPeer.CreatePeerForElement(element); if (peer == null) { FrameworkElement elementFE = element as FrameworkElement; if (elementFE != null) peer = new FrameworkElementAutomationPeer(elementFE); else peer = new UIElementAutomationPeer(element); } return peer; }
protected override List <AutomationPeer> GetChildrenCore() { if (OwningCalendar.MonthControl == null) { return(null); } List <AutomationPeer> peers = new List <AutomationPeer>(); Dictionary <DateTimeCalendarModePair, DateTimeAutomationPeer> newChildren = new Dictionary <DateTimeCalendarModePair, DateTimeAutomationPeer>(); // Step 1: Add previous, header and next buttons AutomationPeer buttonPeer; buttonPeer = FrameworkElementAutomationPeer.CreatePeerForElement(OwningCalendar.MonthControl.PreviousButton); if (buttonPeer != null) { peers.Add(buttonPeer); } buttonPeer = FrameworkElementAutomationPeer.CreatePeerForElement(OwningCalendar.MonthControl.HeaderButton); if (buttonPeer != null) { peers.Add(buttonPeer); } buttonPeer = FrameworkElementAutomationPeer.CreatePeerForElement(OwningCalendar.MonthControl.NextButton); if (buttonPeer != null) { peers.Add(buttonPeer); } // Step 2: Add Calendar Buttons depending on the Calendar.DisplayMode DateTime date; DateTimeAutomationPeer peer; foreach (UIElement child in this.OwningGrid.Children) { int childRow = (int)child.GetValue(Grid.RowProperty); // first row is day titles if (OwningCalendar.DisplayMode == CalendarMode.Month && childRow == 0) { AutomationPeer dayTitlePeer = UIElementAutomationPeer.CreatePeerForElement(child); if (dayTitlePeer != null) { peers.Add(dayTitlePeer); } } else { Button owningButton = child as Button; if (owningButton != null && owningButton.DataContext is DateTime) { date = (DateTime)owningButton.DataContext; peer = GetOrCreateDateTimeAutomationPeer(date, OwningCalendar.DisplayMode, /*addParentInfo*/ false); peers.Add(peer); DateTimeCalendarModePair key = new DateTimeCalendarModePair(date, OwningCalendar.DisplayMode); newChildren.Add(key, peer); } } } DateTimePeers = newChildren; return(peers); }
virtual internal AutomationPeer GetWrapperPeer() { AutomationPeer wrapperPeer = null; UIElement wrapper = GetWrapper(); if(wrapper != null) { wrapperPeer = UIElementAutomationPeer.CreatePeerForElement(wrapper); if(wrapperPeer == null) //fall back to default peer if there is no specific one { if(wrapper is FrameworkElement) wrapperPeer = new FrameworkElementAutomationPeer((FrameworkElement)wrapper); else wrapperPeer = new UIElementAutomationPeer(wrapper); } } return wrapperPeer; }
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) { // 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 = CreateItemAutomationPeer(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(); } // Step4: Add RibbonTabs List<AutomationPeer> ribbonTabs = base.GetChildrenCore(); if (ribbonTabs != null && ribbonTabs.Count > 0) { children.AddRange(ribbonTabs); } // 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; }
public FrameworkElementAutomationPeer(FrameworkElement owner) { if (owner == null) { throw new ArgumentNullException("owner"); } this.owner = owner; isKeyboardFocusable = null; // Default Automation events owner.SizeChanged += (o, s) => { Point location = GetLocation(owner); RaisePropertyChangedEvent(AutomationElementIdentifiers.BoundingRectangleProperty, new Rect(0, 0, s.PreviousSize.Width, s.PreviousSize.Height), new Rect(location.X, location.Y, s.NewSize.Width, s.NewSize.Height)); }; owner.UIAVisibilityChanged += (o, e) => { IAutomationCacheProperty cachedProperty = GetCachedProperty(AutomationElementIdentifiers.BoundingRectangleProperty); Rect newValue = GetBoundingRectangle(); RaisePropertyChangedEvent(AutomationElementIdentifiers.BoundingRectangleProperty, cachedProperty.OldValue, newValue); RaiseIsKeyboardFocusableEvent(); bool isOffscreen = IsOffscreen(); RaisePropertyChangedEvent(AutomationElementIdentifiers.IsOffscreenProperty, !isOffscreen, isOffscreen); }; Control control = owner as Control; if (control != null) { control.IsEnabledChanged += (o, e) => { RaisePropertyChangedEvent(AutomationElementIdentifiers.IsEnabledProperty, e.OldValue, e.NewValue); RaiseIsKeyboardFocusableEvent(); }; control.UIAIsTabStopChanged += (o, e) => { RaiseIsKeyboardFocusableEvent(); }; // StructureChanged ContentControl contentControl = control as ContentControl; if (contentControl != null) { contentControl.UIAContentChanged += OnContentChanged; AddItemsChangedToPanel(contentControl.Content); } } // SWA.AutomationProperties events owner.AcceleratorKeyChanged += (o, e) => { RaisePropertyChangedEvent(AutomationElementIdentifiers.AcceleratorKeyProperty, e.OldValue, e.NewValue); }; owner.AccessKeyChanged += (o, e) => { RaisePropertyChangedEvent(AutomationElementIdentifiers.AccessKeyProperty, e.OldValue, e.NewValue); }; owner.AutomationIdChanged += (o, e) => { RaisePropertyChangedEvent(AutomationElementIdentifiers.AutomationIdProperty, e.OldValue, e.NewValue); }; owner.HelpTextChanged += (o, e) => { RaisePropertyChangedEvent(AutomationElementIdentifiers.HelpTextProperty, e.OldValue, e.NewValue); }; owner.IsRequiredForFormChanged += (o, e) => { RaisePropertyChangedEvent(AutomationElementIdentifiers.IsRequiredForFormProperty, e.OldValue, e.NewValue); }; owner.ItemStatusChanged += (o, e) => { RaisePropertyChangedEvent(AutomationElementIdentifiers.ItemStatusProperty, e.OldValue, e.NewValue); }; owner.ItemTypeChanged += (o, e) => { RaisePropertyChangedEvent(AutomationElementIdentifiers.ItemTypeProperty, e.OldValue, e.NewValue); }; // LabeledBy and Name properties are "special" because they somehow depend on each other. owner.LabeledByChanged += (o, e) => { RaisePropertyChangedEvent(AutomationElementIdentifiers.LabeledByProperty, e.OldValue, e.NewValue); // Name property UIElement labeledByOld = e.OldValue as UIElement; if (labeledByOld != null) { FrameworkElementAutomationPeer peer = FrameworkElementAutomationPeer.CreatePeerForElement(labeledByOld) as FrameworkElementAutomationPeer; if (peer != null) { peer.NameChanged -= LabeledBy_NameChanged; } } UIElement labeledByNew = e.NewValue as UIElement; if (labeledByNew != null) { FrameworkElementAutomationPeer peer = FrameworkElementAutomationPeer.CreatePeerForElement(labeledByNew) as FrameworkElementAutomationPeer; if (peer != null) { peer.NameChanged += LabeledBy_NameChanged; } } RaiseNameChanged(); }; owner.NameChanged += (o, e) => RaiseNameChanged(); }