How do I select an item in a custom ComboBox with Microsoft UI Automation? I have ComboBox that looks like this:
<ComboBox AutomationProperties.AutomationId="Rm8Function"
ItemsSource="{Binding Source={StaticResource Functions}}"
SelectedItem="{Binding Function, UpdateSourceTrigger=PropertyChanged}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock
Text="{Binding Mode=OneTime, Converter={StaticResource FunctionEnumConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
I.e. I have overriden the ItemTemplate with a custom DataTemplate.
However, now I am not able to select the item using the answer on selecting combobox item using ui automation:
public static void SelectComboBoxItem(this AutomationElement comboBox, string item)
{
var expandCollapsePattern = comboBox.GetPattern<ExpandCollapsePattern>(ExpandCollapsePatternIdentifiers.Pattern);
expandCollapsePattern.Expand();
expandCollapsePattern.Collapse();
var listItem = comboBox.FindFirst(TreeScope.Subtree,
new PropertyCondition(AutomationElement.NameProperty, item));
var selectionItemPattern = listItem.GetPattern<SelectionItemPattern>(SelectionItemPatternIdentifiers.Pattern);
selectionItemPattern.Select();
}
public static T GetPattern<T>(this AutomationElement element, AutomationPattern pattern) where T: BasePattern
{
try
{
return (T) element.GetCurrentPattern(pattern);
}
catch (InvalidOperationException)
{
element.PrintSupportedPatterns();
throw;
}
}
It throws an error telling me that SelectionItemPatternIdentifiers.Pattern
is an unsupported pattern. It's only SynchronizedInputPatternIdentifiers.Pattern
that is supported by the element it's trying to select in the ComboBox.
How should I write my DataTemplate so that it becomes selectable?
I re-defined my ComboBox
in the following way:
<ComboBox AutomationProperties.AutomationId="Rm8Function"
ItemsSource="{Binding Source={StaticResource Functions}}"
SelectedItem="{Binding Function, UpdateSourceTrigger=PropertyChanged}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock
AutomationProperties.Name="{Binding Mode=OneTime, Converter={StaticResource FunctionEnumConverter}}"
Text="{Binding Mode=OneTime, Converter={StaticResource FunctionEnumConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Giving the TextBlock
the same AutomationProperties.Name
value as its Text
value.
I also updated my function that selects the ComboBox item to the following:
public static void SelectComboBoxItem(this AutomationElement comboBox, string item)
{
var expandCollapsePattern = comboBox.GetPattern<ExpandCollapsePattern>(ExpandCollapsePatternIdentifiers.Pattern);
expandCollapsePattern.Expand();
expandCollapsePattern.Collapse();
var listItem = comboBox.FindFirst(TreeScope.Subtree,
new PropertyCondition(AutomationElement.NameProperty, item));
var walker = TreeWalker.ControlViewWalker;
var parent = walker.GetParent(listItem);
while (parent != comboBox)
{
listItem = parent;
parent = walker.GetParent(listItem);
}
var selectionItemPattern = listItem.GetPattern<SelectionItemPattern>(SelectionItemPatternIdentifiers.Pattern);
selectionItemPattern.Select();
}
Apparently, when using a ComboBox
as-is without overriding the ItemTemplate
, the function above finds its immediate child which is a ListBoxItem
. It's the ListBoxItem
that is selectable through the SelectionItemPattern
pattern. But when overriding the ItemTemplate
, the function instead finds the TextBlock
that is a child to the ListBoxItem
. Therefore, I had to modify my function in such a way that it traverses upwards until it finds the immediate child to the ComboBox
and selects it.