Dela via


Writing extension for WPF custom control

Ever since I wrote extensibility series on Coded UI Test, I have been getting lot of good feedback via questions and comments. One learning that I got from this is there are folks out there wanting to use the extensibility and are not able to easily do so. We need to simplify the extensibility interfaces in the future release.

Based on the questions from various folks, I saw two common usage patterns for extensibility.  The first one is -

  • User has custom WPF control with good accessibility.  User wants to support it as rich control with good recording, playback and properties for validation and not as default of WpfControl.

In this blog, I will cover this scenario with a specific example.  Overall, the extensibility points for this scenario are same as the one mentioned in previous extensibility series and going through the earlier series is pre-requisite .

So, what is special about custom WPF control? The answer is WPF has windowless controls i.e. only some controls like “Window” control has actual window handle and other controls like “Button” or “ListBox” are all natively painted without their own window handle. This is not the case with Win32 technologies like Windows Forms or MFC where most control have their own window handle.  So, how does this matter? The reason this matter is one of the central method in Coded UI Test extensibility story is UITechnologyManager.GetControlSupportLevel() which takes a window handle as an input.  This means the technology manager has to handle complete window; users don’t want to do this – they want to just handle their custom control which is there in the window along with other controls.  Well, the solution for this is to aggregate (as in COM sense) the default WPF technology manager in the custom control technology manager and delegate calls as appropriate to WPF technology manager.

Attached is the sample.  The sample has 3 parts -

  1. Application – This is sample application that includes a custom control.  The custom control here is NumericUpDown control (on lines of Windows Forms NumericUpDown). The control consists of a TextBox and two RepeatButton. The application and the control is just a sample for this illustration (given my limited proficiency with WPF).
  2. Extension – This is actual extension that has technology manager and property providers to support the above custom control as rich WpfNumericUpDown control with well defined properties and richer intent recording. This is further explained below.
  3. Test – This is sample test project showing how playback\validation for this custom control is same as any other control. For recording, you can play with the control.

The Application and Test part of the solution are straight forward and I am not going to explain those any further.  To install and play with the extension, follow the steps mentioned in the series here. In addition, you will need to put the Sample.UITest.WpfNumericUpDown.Extension.dll in the GAC.

In the Extension, we have following files -

  • NudExtensionPackage – The extension package returns NudTechnologyManager as the technology manager and WrappedPropertyProvider & NudPropertyProvider as property providers.
  • NudTechnologyManager – This is the technology manager that is wrapping the default WPF technology manager. It does following -
    • Gets the WPF technology manager as inner manager by using Playback.GetCoreTechnologyManager() API.
    • It delegates most of the call to this inner manager except below ones.
    • GetControlSupportLevel – Here, it inspects to see if this is window of interest and if so, it returns weight more than the default WPF plugin so that it gets picked over the default one.
    • AddEventHandler – Here when the control is TextBox or RepeatButton inside NumericUpDown control, it listens to the value changed event of the TextBox (using inner manager) but fires the event as if it is coming from NumericUpDown.
    • RemoveEventHandler – Ensures reverse mapping to remove listener from the inner manager.
    • All methods that return IUITechnologyElement – Here it maps the IUITechnologyElement that it gets from inner manager to either WrappedTechnologyElement (for all except NumericUpDown) and NudTechnologyElement (for NumericUpDown).
  • WrappedTechnologyElement – This just wraps the WPF UITechnologyElement as the inner element with two differences which are it overrides TechnologyName and TechnologyManager properties to route all technology manager calls to NudTechnologyManager.
  • NudTechnologyElement – This inherits from WrappedTechnologyElement and lets you override any other method for the specific control that you are supporting.  Here, I am overriding the QueryId property which represents the search criteria used during playback to identify the control.
  • WrappedPropertyProvider – This is equivalent of WrappedTechnologyElement on the property provider side.
  • NudPropertyProvider – This is equivalent of NudTechnologyElement on the property provider side.
  • WpfNumericUpDown – This is the specialized class for NumericUpDown control that users of this extension will see in their code.  The class derives from the WpfControl and adds the control specific properties.
  • Utilities – Miscellaneous utilities.

With above details, comments in the code and some debugging on your own, you should be able to understand what is going on here.  Overall, there are some hacks and more code that I would have liked to get the entire scenario working. We will look into making this simpler in future release but folks interested in supporting this scenario now should be able to leverage significant portion of the code from here.

WpfNumericUpDown.zip

Comments

  • Anonymous
    July 08, 2010
    How can i write the extensibilty for a Win Control to use UIA technology. I modified the technology manager to UIA as mentioned in the example.It uses the UIA technology but it gets identified as WPF control. How can i make it as a WinControl ?

  • Anonymous
    July 08, 2010
    I able to use UIA technology for a Win form control but not able to display it as WinControl. Instead it is shown as WPF control. How can i make it as WinControl. Do i need to write a UITestPropertyProvider class? Which proeprty will make sure that that the control and its children use UIA technology but shown as WinControl.

  • Anonymous
    July 12, 2010
    The comment has been removed

  • Anonymous
    January 03, 2011
    why cannot download the attached codes on this post? the link seemed expired.

  • Anonymous
    January 05, 2011
    The comment has been removed

  • Anonymous
    February 17, 2011
    The comment has been removed

  • Anonymous
    February 18, 2011
    Good post! What would be amazing is to also have the solution take care of the deploying / undeploying stuff as part of the build / clean events, preferably using MsBuild tasks.

  • Anonymous
    February 20, 2011
    @alex - Thanks for the suggestion.  Not sure if you have figured out your issue already.  If you haven't this could be deploying issue or Office not installed (at least the .NET interop piece).

  • Anonymous
    February 25, 2011
    Hi Gautam, excellent post! I am attempting to create an extension library for the Infragistics UltraGrid class (to start with) and wanted to know if there is an interface that I can implement in my class definition for InfUltraGrid (class similar to WpfNumericUpDown.cs in your example)? Since your example derives the custom object from the Presentation library whereas mine doesn't, I am a little lost on how I can approach a solution and would appreciate your assistance. Please let me know if you need more specifics.

  • Anonymous
    February 27, 2011
    Hi Ravi - We have looked at Ultra Grid and there are known issues there because of which writing extension for it in this release will not be possible.  These issues are being considered for future releases.  At this point, you will not be able to use Coded UI Test for Ultra Grid. Sorry about that.

  • Anonymous
    August 23, 2011
    Hi Gautam,I have a question now.I defined a WpfTabPage to select a control using TabPage.SearchProperties[WpfTabPage.PropertyNames.Name]. But it is not very stable and some time Test can not select the control.I do not know why it is.

  • Anonymous
    August 23, 2011
    The comment has been removed

  • Anonymous
    May 07, 2012
    Hi there what is the case when i have a Wpf app - when i move the "target cross" (at the codedui builder) on the main window - it regognize it and give me its params. but when i try to stand on an inner cotrol the "target cross" doesnt recognize it as control at all, and doesnt allow me to point the inner controls,  

  • Anonymous
    May 08, 2012
    @Aharon - This means the control has not exposed inner control properly via accessibility.  Check other commentquestion that you asked on my blog for links to accessibility.

  • Anonymous
    May 08, 2012
    ok -so if i will add custom property to my each control and will use "itemStatus" to recognize its control - will then i would be able to locate it? as well what is the advantage of using "TechnolayManager" (like your numeric exsample) comparing using location by "itemStatus"? Best.