// Process all the Logical and Raw Element Properties internal override object GetElementProperty(AutomationProperty idProp) { if (idProp == AutomationElement.IsPasswordProperty) { return(_type == WindowsEditBox.EditboxType.Password); } else if (idProp == AutomationElement.NameProperty) { // Per ControlType.Edit spec if there is no static text // label for an Edit then it must NEVER return the contents // of the edit as the Name property. This relies on the // default ProxyHwnd impl looking for a label for Name and // not using WM_GETTEXT on the edit hwnd. string name = base.GetElementProperty(idProp) as string; if (string.IsNullOrEmpty(name)) { // Stop UIA from asking other providers return(AutomationElement.NotSupported); } return(name); } return(base.GetElementProperty(idProp)); }
// </Snippet103> // <Snippet104> ///-------------------------------------------------------------------- /// <summary> /// Gets the current property values from target. /// </summary> /// <param name="gridItemPattern"> /// A GridItemPattern control pattern obtained from /// an automation element representing a target control. /// </param> /// <param name="automationProperty"> /// The automation property of interest. /// </param> /// <returns> /// An integer object representing the requested property value. /// </returns> ///-------------------------------------------------------------------- private object GetGridItemProperties( GridItemPattern gridItemPattern, AutomationProperty automationProperty) { if (automationProperty.Id == GridItemPattern.ColumnProperty.Id) { return(gridItemPattern.Current.Column); } if (automationProperty.Id == GridItemPattern.RowProperty.Id) { return(gridItemPattern.Current.Row); } if (automationProperty.Id == GridItemPattern.ColumnSpanProperty.Id) { return(gridItemPattern.Current.ColumnSpan); } if (automationProperty.Id == GridItemPattern.RowSpanProperty.Id) { return(gridItemPattern.Current.RowSpan); } return(null); }
public void VerifyPrimaryCommandsAutomationSet() { if (PlatformConfiguration.IsOSVersionLessThan(OSVersion.Redstone2)) { Log.Warning("Test is disabled pre-RS2 because CommandBarFlyout is not supported pre-RS2"); return; } using (var setup = new CommandBarFlyoutTestSetupHelper()) { Button showCommandBarFlyoutButton = FindElement.ByName <Button>("Show CommandBarFlyout"); Log.Comment("Tap on a button to show the CommandBarFlyout."); InputHelper.Tap(showCommandBarFlyoutButton); Button cutButton1 = FindElement.ById <Button>("CutButton1"); var cutButtonElement = AutomationElement.FocusedElement; Verify.AreEqual(cutButtonElement.Current.AutomationId, cutButton1.AutomationId); int sizeOfSet = (int)cutButtonElement.GetCurrentPropertyValue(AutomationProperty.LookupById(UIA_SizeOfSetPropertyId)); int positionInSet = (int)cutButtonElement.GetCurrentPropertyValue(AutomationProperty.LookupById(UIA_PositionInSetPropertyId)); Log.Comment("Verify first primary command's SizeOfSet and PositionInSet automation properties."); Verify.AreEqual(sizeOfSet, 7); Verify.IsTrue(positionInSet == -1 || positionInSet == 1); Log.Comment("Press Right key to move focus to last primary command: Underline."); for (int i = 0; i <= 4; i++) { KeyboardHelper.PressKey(Key.Right); Wait.ForIdle(); } Button underlineButton1 = FindElement.ById <Button>("UnderlineButton1"); var underlineButtonElement = AutomationElement.FocusedElement; Verify.AreEqual(underlineButtonElement.Current.AutomationId, underlineButton1.AutomationId); sizeOfSet = (int)underlineButtonElement.GetCurrentPropertyValue(AutomationProperty.LookupById(UIA_SizeOfSetPropertyId)); positionInSet = (int)underlineButtonElement.GetCurrentPropertyValue(AutomationProperty.LookupById(UIA_PositionInSetPropertyId)); Log.Comment("Verify last primary command's SizeOfSet and PositionInSet automation properties."); Verify.AreEqual(sizeOfSet, 7); Verify.IsTrue(positionInSet == -1 || positionInSet == 6); Log.Comment("Press Right key to move focus to MoreButton."); KeyboardHelper.PressKey(Key.Right); Wait.ForIdle(); Button moreButton = FindElement.ById <Button>("MoreButton"); var moreButtonElement = AutomationElement.FocusedElement; Verify.AreEqual(moreButtonElement.Current.AutomationId, moreButton.AutomationId); sizeOfSet = (int)moreButtonElement.GetCurrentPropertyValue(AutomationProperty.LookupById(UIA_SizeOfSetPropertyId)); positionInSet = (int)moreButtonElement.GetCurrentPropertyValue(AutomationProperty.LookupById(UIA_PositionInSetPropertyId)); Log.Comment("Verify MoreButton's SizeOfSet and PositionInSet automation properties."); Verify.AreEqual(sizeOfSet, 7); Verify.AreEqual(positionInSet, 7); } }
// See if this element has a specified property with specified value. private static bool IsElementWithPropertyValue(AutomationElement root, AutomationProperty property, object value, bool allowPartialMatch) { // Get the value and see if you found it. object actualValue = root.GetCurrentPropertyValue(property); if (value.Equals(actualValue)) { return(true); } // Assume that the value is a string if allowPartialMatch is true. if (allowPartialMatch) { string expectedString = value as string; string actualString = actualValue as string; if (actualString == null) { return(false); } Debug.Assert(expectedString != null, "value must be string when allowPartialMatch is true."); if (actualString.ToLower().IndexOf(expectedString.ToLower()) != -1) { return(true); } } return(false); }
public AutomationElement GetMainWindow(AutomationProperty searchBy, object value, int timeoutSecond = 3600) { timeoutSecond = (this.TimeoutSecond == 0) ? timeoutSecond : this.TimeoutSecond; var desktop = AutomationElement.RootElement; return(GetControlTileEnable(searchBy, value, false, timeoutSecond, desktop)); }
private static void RegisterStandalonePropertyGetter(AutomationProperty automationProperty) { // With WPF Automation peers, retrieving UIA property value goes through these steps: // 1. UIA request comes at ElementProxy which linked with AutomationPeer and wraps it from multithreading, COM etc // 2. ElementProxy passes request to UI thread and directs it to AutomationPeer.GetPropertyValue(int propertyId) // 3. AutomationPeer consults its hashtable of getters and tries to find there getter for required property. These // getters are basically Func<AutomationPeer, object> // 4. If getter is found - it is called like getter(this) from AutomationPeer, otherwise null returned // // Similarly to RegisterPattern() method, we need to add new item to // private static Hashtable AutomationPeer.s_propertyInfo, in order to let 3rd step from above pass correctly // Like this line // AutomationPeer.s_propertyInfo[property.PropertyId] = new AutomationPeer.GetProperty(getter); // where GetProperty defined in AutomationPeer as: // private delegate object GetProperty(AutomationPeer peer); // // Our getter will try to cast AutomationPeer to IStandalonePropertyProvider and if successful - get result from it. // Otherwise returns null. var automationPeerType = typeof(AutomationPeer); var propertyInfoHashtableField = automationPeerType.GetField("s_propertyInfo", BindingFlags.NonPublic | BindingFlags.Static); var getterDelegateType = automationPeerType.GetNestedType("GetProperty", BindingFlags.NonPublic); var getterObject = new StandalonePropertyGetter(automationProperty); var getterMethodInfo = ReflectionUtils.GetMethodInfo(() => getterObject.Getter(null)); var getter = Delegate.CreateDelegate(getterDelegateType, getterObject, getterMethodInfo); using (Dispatcher.CurrentDispatcher.DisableProcessing()) { var propertyHashtable = (Hashtable)propertyInfoHashtableField.GetValue(null); propertyHashtable[automationProperty.Id] = getter; } }
public RangeBaseAutomationPeer(RangeBase owner) : base(owner) { // UIA Event RangeValuePatternIdentifiers.ValueProperty // Raised by RangeBase.OnValuePropertyChanged() owner.IsEnabledChanged += (o, e) => { RaisePropertyChangedEvent(RangeValuePatternIdentifiers.IsReadOnlyProperty, e.OldValue, e.NewValue); }; owner.UIAPropertyChanged += (o, e) => { AutomationProperty property = null; switch (e.Change) { case RangeBase.Change.Large: property = RangeValuePatternIdentifiers.LargeChangeProperty; break; case RangeBase.Change.Small: property = RangeValuePatternIdentifiers.SmallChangeProperty; break; case RangeBase.Change.Maximum: property = RangeValuePatternIdentifiers.MaximumProperty; break; case RangeBase.Change.Minimum: property = RangeValuePatternIdentifiers.MinimumProperty; break; } RaisePropertyChangedEvent(property, e.OldValue, e.NewValue); }; }
public static void SetCheckBoxByPreviousControl(this TestBase @this, AutomationProperty searchBy, object value, bool checkIn, AutomationElement labelRetrievedControl = null) { var label = @this.App.FindDescendant(searchBy, value, labelRetrievedControl); var checkBox = @this.App.FindNextSibling(label); ControlProvider.Transfer <AECheckBox>(checkBox).Check(checkIn); }
public static void ClickButtonByChildElement(this TestBase @this, AutomationProperty searchBy, object value, AutomationElement retrievedControl = null) { var child = @this.App.FindDescendant(searchBy, value, retrievedControl); var target = @this.App.FindParent(child); ControlProvider.Transfer <AEButton>(target).Click(); }
public static void SelectListByPreviousControl(this TestBase @this, AutomationProperty searchBy, object value, int itemIndex, AutomationElement labelRetrievedControl = null) { var label = @this.App.FindDescendant(searchBy, value, labelRetrievedControl); var comboBox = @this.App.FindNextSibling(label); ControlProvider.Transfer <AEComboBox>(comboBox).Select(itemIndex); }
public static void EnterTextByPreviousControl(this TestBase @this, AutomationProperty searchBy, object value, string text, AutomationElement labelRetrievedControl = null) { var label = @this.App.FindDescendant(searchBy, value, labelRetrievedControl); var comboBox = @this.App.FindNextSibling(label); ControlProvider.Transfer <AEEdit>(comboBox).Set(text); }
/// <summary> /// Removes a previously added property changed event handler /// </summary> /// <param name="hWnd">window handle</param> /// <param name="property">the property to remove</param> /// <param name="element">the control in the window</param> /// <param name="eventHandler">the eveht handler to remove</param> static public void RemoveAutomationPropertyChangedEventHandler(IntPtr hWnd, AutomationProperty property, AutomationElement element, AutomationPropertyChangedEventHandler eventHandler) { Log.Debug(); if (hWnd == IntPtr.Zero) { return; } lock (WindowTable) { var windowElement = (WindowElement)WindowTable[hWnd]; if (windowElement != null) { var item = new RemoveAutomationPropertyChangedItem { Property = property, AutoElement = element, EventHandler = eventHandler, WinElement = windowElement }; RemoveAutomationPropertyChanged(item); //windowElement.RemoveAutomationPropertyChangedEventHandler(element, property, eventHandler); } } }
/// <summary> /// Adds a property changed automation event handler /// </summary> /// <param name="hWnd">window handle</param> /// <param name="property">the property to track</param> /// <param name="element">the element in the window to track</param> /// <param name="eventHandler">the event handler</param> static public void AddAutomationPropertyChangedEventHandler(IntPtr hWnd, AutomationProperty property, AutomationElement element, AutomationPropertyChangedEventHandler eventHandler) { lock (WindowTable) { var windowElement = (WindowElement)WindowTable[hWnd]; if (windowElement == null) { windowElement = new WindowElement(hWnd); WindowTable.Add(hWnd, windowElement); windowElement.EvtOnWindowClosed += windowElement_EvtOnWindowClosed; } var item = new AddAutomationPropertyChangedItem { Property = property, AutoElement = element, EventHandler = eventHandler, WinElement = windowElement }; AddAutomationPropertyChanged(item); } }
// Process all the Logical and Raw Element Properties internal override object GetElementProperty(AutomationProperty idProp) { if (idProp == AutomationElement.IsControlElementProperty) { // // The panes under the rebar band should not be in the control view. // // In IE6, the rebar band HWND tree was only one level deep: // // rebar / rebar band / rebar item (Toolbar32) // // In IE7, the HWND tree is the same but the rebar item is // a window acting as another container, for instance: // // rebar / rebar band / rebar item (FavBandClass) / children (Toolbar32) // // Hide windows that are intermediate containers from the control view Accessible accThis = Accessible.Wrap(this.AccessibleObject); if ((accThis != null) && (accThis.ChildCount == 1)) { Accessible accWind = accThis.FirstChild; if ((accWind != null) && (accWind.Role == AccessibleRole.Window)) { return(false); } } } // No property should be handled by the override proxy // Overrides the ProxySimple implementation. return(null); }
internal ByProperty(TreeScope scope, AutomationProperty property, object value) { this.scope = scope; this.infoList = new List <Info> { new Info(property, value, ConditionType.None) }; }
public IElement FindFirst(IElement context, LocatorStrategy strategy, string locator) { AutomationProperty property = this.ToAutomationProperty(strategy); AutomationElement element = null; switch (strategy) { case LocatorStrategy.Id: case LocatorStrategy.Name: case LocatorStrategy.ClassName: element = context.AutomationElement.FindFirst( TreeScope.Descendants, new PropertyCondition(property, locator)); break; case LocatorStrategy.TagName: ControlType type = this.uiAutomation.FromTagName(locator); element = context.AutomationElement.FindFirst( TreeScope.Descendants, new PropertyCondition(property, type)); break; case LocatorStrategy.XPath: element = this.uiAutomation.FindFirstByXPath(context.AutomationElement, locator); break; default: throw new FailedCommandException( string.Format("Usupported locator startegy: {0}", strategy.ToString()), 32); // InvalidSelector (32) } return(element == null ? null : this.elementFactory.GetElement(element)); }
/// <summary> /// Walks the Automation Tree from the specified root, searching for the element with the given property. /// (Stolen from HostingHelper used by DrtLaunchContainer) /// </summary> /// <param name="root">The root to start searching from</param> /// <param name="property">The property to search for</param> /// <param name="value">The possible values of above property</param> /// <param name="maxDepth">The maximum depth to search</param> /// <param name="allowPartialMatch">Allow partial matches (i.e. for window titles)</param> /// <returns></returns> public static AutomationElement FindElementWithPropertyValue(AutomationElement root, AutomationProperty property, object[] values, int maxDepth, bool allowPartialMatch) { AutomationElement outElement = null; DateTime end = DateTime.Now.AddMilliseconds(Timeout); while ((outElement == null) && (DateTime.Now < end)) { foreach (object value in values) { if (FindElementWithPropertyValueImpl(root, property, value, maxDepth, allowPartialMatch, 0 /* currentDepth */, ref outElement)) { break; } System.Threading.Thread.Sleep(Interval); } } TestServices.Assert( outElement != null, "The specified element was not found. Looking for values:", values); return(outElement); }
// Process all the Logical and Raw Element Properties internal override object GetElementProperty(AutomationProperty idProp) { if (idProp == AutomationElement.IsControlElementProperty) { return(IsValidControl(_hwnd)); } else if (idProp == AutomationElement.OrientationProperty) { return(IsVerticalTab() ? OrientationType.Vertical : OrientationType.Horizontal); } else if (idProp == ScrollPatternIdentifiers.HorizontalScrollPercentProperty) { return(((IScrollProvider)this).HorizontalScrollPercent); } else if (idProp == ScrollPatternIdentifiers.HorizontallyScrollableProperty) { return(((IScrollProvider)this).HorizontallyScrollable); } else if (idProp == ScrollPatternIdentifiers.HorizontalViewSizeProperty) { return(((IScrollProvider)this).HorizontalViewSize); } return(base.GetElementProperty(idProp)); }
private static void RaiseEventsOnWindow(IntPtr hwnd, int eventId, object idProp, int idObject, int idChild) { AutomationProperty automationProperty = idProp as AutomationProperty; ProxySimple el = null; if ((eventId == NativeMethods.EventObjectShow || eventId == NativeMethods.EventObjectHide) && (automationProperty != null && automationProperty == ExpandCollapsePattern.ExpandCollapseStateProperty)) { if (Misc.IsBitSet(Misc.GetWindowStyle(hwnd), NativeMethods.LBS_COMBOBOX)) { // List portion of combo: We'll hit it in the case when user hovers over it NativeMethods.COMBOBOXINFO cbInfo = new NativeMethods.COMBOBOXINFO(NativeMethods.comboboxInfoSize); if (WindowsComboBox.GetComboInfo(hwnd, ref cbInfo) && (cbInfo.hwndCombo != IntPtr.Zero)) { WindowsComboBox cb = (WindowsComboBox)WindowsComboBox.Create(cbInfo.hwndCombo, 0); if (!cb.IsSimpleCombo()) { el = cb; } } } } if (el != null) { el.DispatchEvents(eventId, idProp, idObject, idChild); } }
// Process the Scroll Properties static internal object GetPropertyScroll(AutomationProperty idProp, IntPtr hwnd) { // ...handle the scroll properties... if (idProp == ScrollPattern.HorizontalScrollPercentProperty) { return(Scrollable(hwnd, NativeMethods.SB_HORZ) ? GetScrollInfo(hwnd, NativeMethods.SB_HORZ) : ScrollPattern.NoScroll); } else if (idProp == ScrollPattern.VerticalScrollPercentProperty) { return(Scrollable(hwnd, NativeMethods.SB_VERT) ? GetScrollInfo(hwnd, NativeMethods.SB_VERT) : ScrollPattern.NoScroll); } else if (idProp == ScrollPattern.HorizontalViewSizeProperty) { return(Scrollable(hwnd, NativeMethods.SB_HORZ) ? ScrollViewSize(hwnd, NativeMethods.SB_HORZ) : 100.0); } else if (idProp == ScrollPattern.VerticalViewSizeProperty) { return(Scrollable(hwnd, NativeMethods.SB_VERT) ? ScrollViewSize(hwnd, NativeMethods.SB_VERT) : 100.0); } else if (idProp == ScrollPattern.HorizontallyScrollableProperty) { return(Scrollable(hwnd, NativeMethods.SB_HORZ)); } else if (idProp == ScrollPattern.VerticallyScrollableProperty) { return(Scrollable(hwnd, NativeMethods.SB_VERT)); } return(null); }
// This function will walk the tree starting at the root and try to find // an element that has the specified value for the specified property. public static AutomationElement FindElementWithPropertyValue(AutomationElement root, AutomationProperty property, object value, int maxDepth, bool allowPartialMatch) { AutomationElement outelement = null; for (int i = 0; i < 45; i++) { Output(false, "Waiting for element with {0}={1}.", property.ProgrammaticName, value); Thread.Sleep(2000); if (FindElementWithPropertyValueImpl(root, property, value, maxDepth, allowPartialMatch, 0 /* currentDepth */, ref outelement)) { break; } } if (outelement == null) { throw new ApplicationException(String.Format("Could not find element with {0}={1}.", property, value)); } return(outelement); }
internal static object WrapObjectAsProperty(AutomationProperty property, object obj) { PropertyTypeInfo info; // Handle the cases that we know. if (obj == AutomationElement.NotSupported) { // No-op } else if (obj is UIAutomationClient.IUIAutomationElement) { obj = AutomationElement.Wrap((UIAutomationClient.IUIAutomationElement)obj); } else if (obj is UIAutomationClient.IUIAutomationElementArray) { obj = Utility.ConvertToElementArray((UIAutomationClient.IUIAutomationElementArray)obj); } else if (Schema.GetPropertyTypeInfo(property, out info)) { // Well known properties if ((obj != null) && (info.ObjectConverter != null)) { obj = info.ObjectConverter(obj); } } return(obj); }
// Process all the Logical and Raw Element Properties internal override object GetElementProperty(AutomationProperty idProp) { // Normal Listview items do not have a concept of an AccessKey. But // the Listview items in the Start Menu does. This information is // in the IAccessible interface implemented by the Shell team. if (idProp == AutomationElement.AccessKeyProperty) { // The IAccessible should be valid here since it is the cached value in ProxySimple. System.Diagnostics.Debug.Assert(AccessibleObject != null, "Failed to get a valid IAccessible!"); try { string key = AccessibleObject.get_accKeyboardShortcut(_item + 1); if (!string.IsNullOrEmpty(key)) { return(ST.Get(STID.KeyAlt) + "+" + key); } } catch (Exception e) { if (Misc.IsCriticalException(e)) { throw; } } } else if (idProp == AutomationElement.HasKeyboardFocusProperty) { return(IsFocused()); } return(base.GetElementProperty(idProp)); }
private static void RaisePropertyChangedEvent(ProxySimple el, AutomationProperty property, object propertyValue) { if (propertyValue != null && propertyValue != AutomationElement.NotSupported) { AutomationInteropProvider.RaiseAutomationPropertyChangedEvent(el, new AutomationPropertyChangedEventArgs(property, null, propertyValue)); } }
public AutomationProperty[] GetSupportedProperties() { return((from propertyId in allPropertyIds let val = provider.GetPropertyValue(propertyId) where val != null && val != AEIds.NotSupported select AutomationProperty.LookupById(propertyId)).ToArray()); }
// Process all the Element Properties internal override object GetElementProperty(AutomationProperty idProp) { if (idProp == AutomationElement.IsOffscreenProperty) { Rect parentRect = GetParent().BoundingRectangle; NativeMethods.Win32Rect itemRect = ListViewCheckBoxRect(_hwnd, _listviewItem); if (itemRect.IsEmpty || parentRect.IsEmpty) { return(true); } if (Misc.MapWindowPoints(_hwnd, IntPtr.Zero, ref itemRect, 2) && !Misc.IsItemVisible(ref parentRect, ref itemRect)) { return(true); } } // EventManager.DispatchEvent() genericaly uses GetElementProperty() // to get properties during a property change event. Proccess ToggleStateProperty // so the ToggleStateProperty Change Event can get the correct state. else if (idProp == TogglePattern.ToggleStateProperty) { return(((IToggleProvider)this).ToggleState); } return(base.GetElementProperty(idProp)); }
public static IEnumerable <Condition> CreateConditionPathForPropertyValues(AutomationProperty property, IEnumerable <object> values) { IEnumerable <PropertyCondition> conditions = values.Select(value => new PropertyCondition(property, value)); return(conditions.Cast <Condition>()); }
protected void TestProperty(AutomationElement element, AutomationProperty property, object expectedValue) { Assert.AreEqual(expectedValue, element.GetCurrentPropertyValue(property), property.ProgrammaticName); }
public bool SupportsProperty(AutomationProperty property) { ArgumentCheck.NotNull(property, "property"); object val = provider.GetPropertyValue(property.Id); return(val != null && val != AEIds.NotSupported); }
public static void TestAutomationProperty(IRawElementProviderSimple provider, AutomationProperty property, object expectedValue) { Assert.AreEqual(expectedValue, provider.GetPropertyValue(property.Id), property.ProgrammaticName); }
internal IAutomationCacheProperty GetCachedProperty (AutomationProperty property) { CacheMainProperties (); return (from p in cacheProperties where p.Property == property select p).FirstOrDefault(); }
public void RaisePropertyChangedEvent (AutomationProperty property, object oldValue, object newValue) { AutomationSingleton.Instance.RaisePropertyChangedEvent (this, property, oldValue, newValue); }
public void RaisePropertyChangedEvent(AutomationProperty property, object oldValue, object newValue) { // Only send the event if there are listeners for this property change if (AutomationInteropProvider.ClientsAreListening) { RaisePropertyChangedInternal(ProviderFromPeer(this), property,oldValue,newValue); } }
// internal handling of structure chanegd events private void RaisePropertyChangedInternal(IRawElementProviderSimple provider, AutomationProperty propertyId, object oldValue, object newValue) { // Callers have only checked if automation clients are present so filter for any interest in this particular event. if ( provider != null && EventMap.HasRegisteredEvent(AutomationEvents.PropertyChanged) ) { AutomationPropertyChangedEventArgs e = new AutomationPropertyChangedEventArgs(propertyId, oldValue, newValue); AutomationInteropProvider.RaiseAutomationPropertyChangedEvent(provider, e); } }
private void SetAutomationEvents (IScrollProvider provider, ScrollBar scrollbar, Func<bool> scrollableDelegate, Func<Visibility> computedVisibilityDelegate, Func<double> scrollPercentDelegate, Func<double> viewSizeDelegate, AutomationProperty scrollPercentProperty, AutomationProperty scrollableProperty, AutomationProperty viewSizeProperty, AutomationOrientation orientation) { CachedProperty cachedProperty; if (orientation == AutomationOrientation.Horizontal) cachedProperty = hCachedProperty; else cachedProperty = vCachedProperty; cachedProperty.Scrollable = scrollableDelegate (); cachedProperty.Visible = computedVisibilityDelegate () == Visibility.Visible; cachedProperty.ScrollPercent = scrollPercentDelegate (); cachedProperty.ViewSize = viewSizeDelegate (); cachedProperty.ScrollPercentProperty = scrollPercentProperty; cachedProperty.ScrollableProperty = scrollableProperty; cachedProperty.ViewSizeProperty = viewSizeProperty; cachedProperty.Orientation = orientation; cachedProperty.ScrollBar = scrollbar; cachedProperty.ScrollPercentDelegate = scrollPercentDelegate; cachedProperty.ScrollableDelegate = scrollableDelegate; scrollViewer.UIAVisibilityChanged += (o, e) => { if (cachedProperty.Orientation != e.Orientation) { RaiseStructureChanged (cachedProperty, computedVisibilityDelegate); RaiseScrollableProperty (cachedProperty, scrollableDelegate); RaiseViewSizeProperty (cachedProperty, viewSizeDelegate); RaiseScrollPercentProperty (cachedProperty, scrollPercentDelegate); } }; scrollViewer.UIAViewportChanged += (o, e) => { if (cachedProperty.Orientation == AutomationOrientation.Horizontal) RaiseViewSizeProperty (cachedProperty, viewSizeDelegate, provider.HorizontalViewSize); else RaiseViewSizeProperty (cachedProperty, viewSizeDelegate, provider.VerticalViewSize); }; scrollViewer.SizeChanged += (o, e) => { RaiseViewSizeProperty (cachedProperty, viewSizeDelegate); }; scrollViewer.UIAOffsetChanged += (o, e) => { if (e.Orientation == cachedProperty.Orientation) RaiseScrollPercentProperty (cachedProperty, scrollPercentDelegate); }; scrollViewer.UIAScrollBarSet += (o, e) => { if (e.Orientation == cachedProperty.Orientation) { if (cachedProperty.ScrollBar != null) { cachedProperty.ScrollBar.IsEnabledChanged -= ScrollBar_IsEnabledChanged; cachedProperty.ScrollBar.ValueChanged -= ScrollBar_ValueChanged; } cachedProperty.ScrollBar = e.NewValue; if (cachedProperty.ScrollBar != null) { cachedProperty.ScrollBar.IsEnabledChanged += ScrollBar_IsEnabledChanged; cachedProperty.ScrollBar.ValueChanged += ScrollBar_ValueChanged; } SetScrollBarAutomationPeer (cachedProperty.ScrollBar, cachedProperty.Orientation); } }; if (cachedProperty.ScrollBar != null) { cachedProperty.ScrollBar.IsEnabledChanged += ScrollBar_IsEnabledChanged; cachedProperty.ScrollBar.ValueChanged += ScrollBar_ValueChanged; } SetScrollBarAutomationPeer (cachedProperty.ScrollBar, cachedProperty.Orientation); }