none
UI Automation: How to make a property of a custom UserControl visible for Inspect? RRS feed

  • Question

  • Hi!


    I'm doing some research for automated testing at the moment and I ran into a problem when using the UI Automation and the Automation Peers.


    In a demo application I create a custom UserControl that basically only holds a Ellipse. I've then created a DependencyProperty called 'EllipseFill' that allows to set the Fill of said Ellipse. From a funtional point of view this works fine already.

    I then tried to make the custom UserControl visible for UI Automation. I therefore implemented a custom AutomationPeer-claas. Now my custom UserControl is visible in Inspect, but unfortunately I fail to make the 'EllipseFill' property visible. I was not able to find a corresponding tutorial on the web - could please someone here help me out?


    Here is my custom UserControl's code:

    public partial class AUIEllipseUserControl : UserControl
        {
            protected override AutomationPeer OnCreateAutomationPeer()
            {
                return new AUIEllipseUserControlAutomationPeer(this);
            }
    
            public AUIEllipseUserControl()
            {
                InitializeComponent();          
            }
    
            private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                AUIEllipseUserControl aui = d as AUIEllipseUserControl;
                if (aui != null && (e.OldValue != e.NewValue))
                {
                    aui.InnerElipse.Fill = e.NewValue as SolidColorBrush;                
                }
            }
            
            public static readonly DependencyProperty EllipseFillProperty = DependencyProperty.Register("EllipseFill", typeof(SolidColorBrush), typeof(AUIEllipseUserControl), new FrameworkPropertyMetadata(OnPropertyChanged));
    
            public SolidColorBrush EllipseFill
            {
                get { return this.GetValue(EllipseFillProperty) as SolidColorBrush; }
                set { this.SetValue(EllipseFillProperty, value); }
            }
    
            private class AUIEllipseUserControlAutomationPeer : FrameworkElementAutomationPeer
            {
    
                public AUIEllipseUserControlAutomationPeer(FrameworkElement owner)
                    : base(owner)
                {
                    if (!(owner is AUIEllipseUserControl))
                        throw new ArgumentOutOfRangeException();
                }
    
                protected override string GetClassNameCore()
                {
                    return "AUIEllipseUserControl";
                }
    
                protected override AutomationControlType GetAutomationControlTypeCore()
                {
                    return AutomationControlType.Custom;
                }
    
                protected override bool IsContentElementCore()
                {
                    return true;
                }
    
                protected override bool IsControlElementCore()
                {
                    return false;
                }
            }
        }

    Any ideas what I have to do to make the 'EllipseFill' property visible?

    Regards

    Ralf



    Tuesday, December 3, 2013 2:05 PM

Answers

  • Nimami is on right track.  MSAA is outdated technology, so using automation peers will work but who needs the headache?  We also know that all WPF controls are by default exposed to the MSFT UITestFramework using what ever technology it does (I don't know specifically what does this).

    But one of the tricks learned in CODEUI mapping is that controls that aren't visible aren't discoverable!  This makes sense because after all we are discovering GUI controls to automate.  If a custom control follows the proper principles of being created which is either using existing controls or your own custom controls using advanced techniques, all properties are visible.  How do we know this?  Because the WPF property system confirms it every single time we implement a property change notification through INPF or a Dependency Property update.  What we don't know is how .NET interfaces with the Native OS. 

    In your code above, the DependencyProperty alone with the CLR Getter Setter wrapper should be sufficient.  I do not believe you need anything else.  Rather this is a problem of visibility.  NOTE that CODEUI tests don't always find the controls they should.  This is because it is not in the same hierarchy as it was when recorded, or it can be something as simple as another control overlapping of covering the control needed.  I suspect that is the type of problem you are having.

    Try this, get rid of all other controls in your application but the custom control, bring it up and tell us if you can see the properties in SPY++.  If you can't see them then, the problem is that the native window doesn't have a one-to-one mapping to the WPF stuff you are implementing.  For example does Win32 even know what a SolidColorBrush is?  Probably not. 


    JP Cowboy Coders Unite!

    • Marked as answer by Yang,Chenfei Wednesday, December 11, 2013 1:14 AM
    Thursday, December 5, 2013 5:58 PM
  • One other trick is to remove all but the custom control.  Then create a CODEUI recording and tell us if it found the control.  I believe it will, but we should take a look at how the mapping occurred for the property you need.

    JP Cowboy Coders Unite!

    • Marked as answer by Yang,Chenfei Wednesday, December 11, 2013 1:14 AM
    Thursday, December 5, 2013 5:59 PM

All replies

  • Hi Ralf,

    Based on my understanding, I thought you want to add Dependency Property to a User control and set the property’s visible.

    I created a sample and quoted your code. In my sample, I can get the 'EllipseFill' property in my Main Window class.

    >> Any ideas what I have to do to make the 'EllipseFill' property visible?

    If you don’t want to get the 'EllipseFill' property in other class, you can set the property accessibility to protected.

    >>I was not able to find a corresponding tutorial on the web - could please someone here help me out?

    Since this sample works fine on my end. For more information about adding Dependency Property to a User control. Please refer to the link below,

    #Exploring the use of Dependency Properties in User Controls

    http://www.codeproject.com/Articles/224230/Exploring-the-use-of-Dependency-Properties-in-User

    If I misunderstood or my points are incorrect, please feel free to let me know.

    Have a nice time!

    Regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, December 4, 2013 2:55 AM
  • Hi Jimmy,


    I think you misunderstood me and that might also be due to the fact that I'm finding it hard to explain my problem, because UI Automation is not my strength as it seems.

    I can easily access the EllipseFill property from code. But for automated tests I would need to be able to see that property of that UserControl at runtime from outside. To verify that this is working (or not working) I was recommended the tool Inspect from Microsoft.

    I've added a screenshot that should be able to clarify the problem. To the left it shows the demo application with a simple Ellipse which is not displayed in Inspect at all. Right underneath the first ellipse is my AUIEllipseUserControl. It is visible in Inspect thanks to the AutomationPeer implementation, but it still lacks the EllipseFill property.

    I hope this clarifies my problem?

    Regards

    Ralf

    Wednesday, December 4, 2013 7:50 AM
  • Hi Ralf,

    Thanks for your clarification!

    I am not sure inspect tool will display dependency property in its data list. For more information about inspect tool, please check out the link below,

    http://msdn.microsoft.com/en-us/library/windows/desktop/dd318521(v=vs.85).aspx

    Inspect (Inspect.exe) is a Windows-based tool that enables you select any UI element and view the element's accessibility data. You can view Microsoft UI Automation properties and control patterns, as well as Microsoft Active Accessibility properties. Inspect also enables you to test the navigational structure of the automation elements in the UI Automation tree, and the accessible objects in the Microsoft Active Accessibility hierarchy.

    Hope this can help you.

    Regards,

    Jimmy


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, December 4, 2013 1:16 PM
  • Hi Jimmy,

    my class contains a public property 'EllipseFill' which is a regular property and a public dependency property 'EllipseFillProperty'. There must be a way to get either of them to be visible in Inspect, don't you think so?

    I just need a hint on how to do this...

    Regards Ralf

    Wednesday, December 4, 2013 1:40 PM
  • Hi Ralf,

    Have you tried it on a built-in WPF Control. Such as TextBox, if the dependency property of Text Box cannot display in Inspect tool. I am afraid it can dispaly the custom usercontrol.

    Regards,

    Wednesday, December 4, 2013 2:19 PM
  • Hi all,

    I´m a tester at Ralfs department and maybe I can help clarifying the problem as well as possible solutions a bit more (unfortunatelly I couln´t get the possible solutions working because my programming skills aren´t good enough 'yet' which is why I asked Ralf :)

    Writing UI-Tests for WPF is usually working fine without any additional work from the programmers because all standard controls expose their relevant properties by default via the UI-Automation framework (until WinForms this was done as Jimmy already said using MSAA).

    Problems however appear when Tests should access properties which are not exposed by default. This can happen with custom controls that aren´t just derived from common controls, but have unique properties built into them. I noticed even some common UI-Elements like a Ellypse is also not accessible by default.

    So, the question was: What has to be done to expose a property during runtime?

    The idea was to use the Elypse as custom control and to expose necessary properties for this custom control, but we couldn´t figure out exactly how.

    We found following usefull info sources (maybe they are also of use to someone researching this topic):

    Infos: Info from MSDN, More info from MSDN

    Example: NumericUpDown Custom Control with Theme and UI Automation Support Sample:

    Example: Custom Controls and UI Automation


    • Edited by NIMAMI Thursday, December 5, 2013 1:38 PM
    Thursday, December 5, 2013 1:37 PM
  • http://msdn.microsoft.com/en-us/library/f7ykdhsy(v=vs.110).aspx 

    Try to use Reflection in .NET. But I am not sure about this can help you.

    Thursday, December 5, 2013 2:49 PM
  • Nimami is on right track.  MSAA is outdated technology, so using automation peers will work but who needs the headache?  We also know that all WPF controls are by default exposed to the MSFT UITestFramework using what ever technology it does (I don't know specifically what does this).

    But one of the tricks learned in CODEUI mapping is that controls that aren't visible aren't discoverable!  This makes sense because after all we are discovering GUI controls to automate.  If a custom control follows the proper principles of being created which is either using existing controls or your own custom controls using advanced techniques, all properties are visible.  How do we know this?  Because the WPF property system confirms it every single time we implement a property change notification through INPF or a Dependency Property update.  What we don't know is how .NET interfaces with the Native OS. 

    In your code above, the DependencyProperty alone with the CLR Getter Setter wrapper should be sufficient.  I do not believe you need anything else.  Rather this is a problem of visibility.  NOTE that CODEUI tests don't always find the controls they should.  This is because it is not in the same hierarchy as it was when recorded, or it can be something as simple as another control overlapping of covering the control needed.  I suspect that is the type of problem you are having.

    Try this, get rid of all other controls in your application but the custom control, bring it up and tell us if you can see the properties in SPY++.  If you can't see them then, the problem is that the native window doesn't have a one-to-one mapping to the WPF stuff you are implementing.  For example does Win32 even know what a SolidColorBrush is?  Probably not. 


    JP Cowboy Coders Unite!

    • Marked as answer by Yang,Chenfei Wednesday, December 11, 2013 1:14 AM
    Thursday, December 5, 2013 5:58 PM
  • One other trick is to remove all but the custom control.  Then create a CODEUI recording and tell us if it found the control.  I believe it will, but we should take a look at how the mapping occurred for the property you need.

    JP Cowboy Coders Unite!

    • Marked as answer by Yang,Chenfei Wednesday, December 11, 2013 1:14 AM
    Thursday, December 5, 2013 5:59 PM
  • Hi Jimmy,

                         I am facing a similar kind of issue while trying to automate Orpheus Custom control testing using Coded UI. 

                            I've already posted my problem in the below link. 

    http://social.msdn.microsoft.com/Forums/en-US/e50c3823-20f8-4c6e-9534-7e24b6123433/accessing-custom-controls-of-delphi-application-using-codedui?forum=vstest

                              Any help is greatly appreciated.

                              Please drop a reply to the above link if you find any solution to the problem explained.

     Regards,

    Vijay.

     

    Friday, September 26, 2014 1:53 AM