Select combobox element using ui automation

How to choose ComboBox SelectedIndex = -1?

I wrote code for testing automation:

AutomationElement aeBuildMachine = null; int count = 0; do { Console.WriteLine("\nLooking for Build Machine Combo Box"); aeBuildMachine = aeTabitemmain.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, "ListBoxItem")); if (aeBuildMachine == null) throw new Exception("No Build Machine Combo Box"); else Console.WriteLine("Found Build Machine Combo Box"); ++count; } while (aeBuildMachine == null && count < 50); Console.WriteLine("Selecting Build machine from combobox..."); SelectionItemPattern spBuildmachine = (SelectionItemPattern)aeBuildMachine.GetCurrentPattern(SelectionItemPattern.Pattern); 

How to use this SelectionItemPattern ?

+7
source share
8 answers

This is about 100 times more complicated than it should be, but I finally got his job. The big problem with WPF ComboBox is that, as far as Automation is concerned, it does not have any ListItems until the ComboBox is expanded .

The following code uses the ExpandCollapse pattern for a short-term drop-down list, and then collapse it, then it can use FindFirst in the ComboBox to select the ListItem, and then use the SelectionItem pattern to select it.

In the case of the original question, a choice of -1 means that no items are selected. There is no way to do this, but you can just use FindAll to get the ListItems collection, get the SelectionItem template for each of them in turn and call its RemoveFromSelection method.

  public static void SetSelectedComboBoxItem(AutomationElement comboBox, string item) { AutomationPattern automationPatternFromElement = GetSpecifiedPattern(comboBox, "ExpandCollapsePatternIdentifiers.Pattern"); ExpandCollapsePattern expandCollapsePattern = comboBox.GetCurrentPattern(automationPatternFromElement) as ExpandCollapsePattern; expandCollapsePattern.Expand(); expandCollapsePattern.Collapse(); AutomationElement listItem = comboBox.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, item)); automationPatternFromElement = GetSpecifiedPattern(listItem, "SelectionItemPatternIdentifiers.Pattern"); SelectionItemPattern selectionItemPattern = listItem.GetCurrentPattern(automationPatternFromElement) as SelectionItemPattern; selectionItemPattern.Select(); } private static AutomationPattern GetSpecifiedPattern(AutomationElement element, string patternName) { AutomationPattern[] supportedPattern = element.GetSupportedPatterns(); foreach (AutomationPattern pattern in supportedPattern) { if (pattern.ProgrammaticName == patternName) return pattern; } return null; } 
+18
source

I thought I would share this as an easy way to select any item from a ComboBox container or another item:

 protected AutomationElement GetItem(AutomationElement element, string item) { AutomationElement elementList; CacheRequest cacheRequest = new CacheRequest(); cacheRequest.Add(AutomationElement.NameProperty); cacheRequest.TreeScope = TreeScope.Element | TreeScope.Children; elementList = element.GetUpdatedCache(cacheRequest); foreach (AutomationElement child in elementList.CachedChildren) if (child.Cached.Name == item) return child; return null; } 
Element

is a container ComboBox or item, item is the name of the string or the literal value of the item in the container. Once you have an element, you can do the following:

 protected void Select(AutomationElement element) { SelectionItemPattern select = (SelectionItemPattern)element.GetCurrentPattern(SelectionItemPattern.Pattern); select.Select(); } 

Hope this helps others. I got this template from the MSDN Automation documentation found here:

MSDN - Automation and Caching of Children

+2
source

This is what worked for me.

  /// <summary> /// Extension method to select item from comboxbox /// </summary> /// <param name="comboBox">Combobox Element</param> /// <param name="item">Item to select</param> /// <returns></returns> public static bool SelectComboboxItem(this AutomationElement comboBox, string item) { if (comboBox == null) return false; // Get the list box within the combobox AutomationElement listBox = comboBox.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.List)); if (listBox == null) return false; // Search for item within the listbox AutomationElement listItem = listBox.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, item)); if (listItem == null) return false; // Check if listbox item has SelectionItemPattern object objPattern; if (true == listItem.TryGetCurrentPattern(SelectionItemPatternIdentifiers.Pattern, out objPattern)) { SelectionItemPattern selectionItemPattern = objPattern as SelectionItemPattern; selectionItemPattern.Select(); // Invoke Selection return true; } return false; } 

Using

  AutomationElement paymentCombobox = element.FindFirst( TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "cbPayment") ); paymentCombobox.SelectComboboxItem("Cash"); 

resource https://msdn.microsoft.com/en-us/library/ms752305(v=vs.110).aspx

+2
source

http://msdn.microsoft.com/de-de/library/system.windows.automation.selectionitempattern_members(v=VS.85).aspx

This is the answer to your question, as I understand it.

But .. is this really your question?

In any case, you can add or remove SelectableItems from a selection that I believe belongs to its parent, the same goes for some other things, such as checking if they are selected.

+1
source

I think this may be the easiest way for a simple universal set of ComobBox values, this option is good if the list items in ComboBox have no duplicates.

 private void SetCombobValueByUIA( AutomationElement ctrl, string newValue ) { ExpandCollapsePattern exPat = ctrl.GetCurrentPattern(ExpandCollapsePattern.Pattern) as ExpandCollapsePattern; if( exPat== null ) { throw new ApplicationException( "Bad Control type..." ); } exPat.Expand(); AutomationElement itemToSelect = ctrl.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty,newValue)); SelectionItemPattern sPat = itemToSelect.GetCurrentPattern( SelectionItemPattern.Pattern) as SelectionItemPattern ; sPat. Select(); } 
+1
source

No big changes, but only a few noticed

  • No need to use the merge pattern, causing a reversal, you will do the trick for you.
  • Using treescope.subtree worked for me instead of children.

An example code would be

 public static void SelectValueInComboBox(string comboBox, string value) { var comboBoxElement = HelperMethods.FindElementFromAutomationID(comboBox); if (comboBoxElement == null) throw new Exception("Combo Box not found"); ExpandCollapsePattern expandPattern = (ExpandCollapsePattern)comboBoxElement.GetCurrentPattern(ExpandCollapsePattern.Pattern); AutomationElement comboboxItem = comboBoxElement.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, value)); SelectionItemPattern selectPattern = (SelectionItemPattern)comboboxItem.GetCurrentPattern(SelectionItemPattern.Pattern); selectPattern.Select(); } 
+1
source

For me, the answer from gotmug required the activation of CacheRequest. I implemented this as an extension method

  public static bool SelectDropDownItem(this AutomationElement comboBoxElement, string item) { bool itemFound = false; AutomationElement elementList; CacheRequest cacheRequest = new CacheRequest(); cacheRequest.Add(AutomationElement.NameProperty); cacheRequest.TreeScope = TreeScope.Element | TreeScope.Children; using (cacheRequest.Activate()) { // Load the list element and cache the specified properties for its descendants. Condition cond = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.List); elementList = comboBoxElement.FindFirst(TreeScope.Children, cond); } //Loop thru and find the actual ListItem foreach (AutomationElement child in elementList.CachedChildren) if (child.Cached.Name == item) { SelectionItemPattern select = (SelectionItemPattern)child.GetCurrentPattern(SelectionItemPattern.Pattern); select.Select(); itemFound = true; break; } return itemFound; } 
0
source
 <pre> public static void SetComboBox(AutomationElement ComboxBox, string SelectedValue) { AutomationElement ListBox = ComboxBox.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "ListBox")); AutomationElement SelectedItem = ListBox.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, SelectedValue)); ((SelectionItemPattern)SelectedItem.GetCurrentPattern(SelectionItemPattern.Pattern)).Select(); } 

Instructions for use: 1) Copy and paste into the utility class 2) Find your ComboBox AutomationElement 3) Utility.SetCombox (ComboxAutomationElement, "SelectedText")

To understand:

The ComboBox tree structure is as follows:

ComboBox-> ListBox (children) → ListItems (children) [each combo box has a ListBox as a child, and a ListBox has all ListItems as a child].

Each ListItem has a SelectedItemPattern that you want to call.

Later I found out that “Shaz” has better coding, and I vote for it as the best code.

** Comment: in order to perform UIAAutomation, you must display the automation elements of your application in TreeView, which makes everything simple and straightforward.

0
source

Source: https://habr.com/ru/post/886853/


All Articles