Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

selecting combobox item using ui automation

Tags:

c#

wpf

how do I select ComboBox's SelectedIndex = -1?

I wrote a code to automate testing:

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 do I use this SelectionItemPattern?

like image 238
jeremychan Avatar asked Apr 28 '11 06:04

jeremychan


5 Answers

This is about 100 times more complicated than it needs to be, but I finally got it working. The big issue with the WPF ComboBox is that as far as Automation goes, it doesn't appear to have any ListItems until the ComboBox has been expanded.

The following code uses the ExpandCollapse pattern to momentarily drop down the list and then collapse it, then it can use FindFirst on the ComboBox to get the ListItem to be selected, and then use the SelectionItem pattern to select it.

In the case of the original question, a selection of -1 means no items selected. There is no method for this, but you could simply use FindAll to get a collection of ListItems, get the SelectionItem pattern for each one 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;
    }
like image 189
SteveWilkinson Avatar answered Nov 15 '22 20:11

SteveWilkinson


I thought I would share this as a simple way to select any item from a ComboBox or other item container:

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 the ComboBox or item container, item is the string name or literal value of the item in the container. Once you have the item you can do the following to select it:

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

Hope this helps others. I derived this pattern from the MSDN documentation on Automation, found here:

MSDN - Automation and Cached Children

like image 29
gotmug Avatar answered Nov 15 '22 19:11

gotmug


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;
    }

Usage

        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

like image 33
Shaz Avatar answered Nov 15 '22 21:11

Shaz


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

That is the answer to your question as I understood it.

But.. is it really your question?

Anyhow, you can add or remove SelectableItems from a selection which - I suppose - belong to its parent, same goes for some other things like checking whether they are selected.

like image 43
Andreas Reiff Avatar answered Nov 15 '22 20:11

Andreas Reiff


I think this might be the easiest way for a simple generic ComobBox value setter this one is fine provided the list items in the ComboBox doesn't have 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();
}
like image 30
Dano Avatar answered Nov 15 '22 20:11

Dano