Select 具有 UI 自动化的自定义 ComboBox 项目

Select custom ComboBox item with UI Automation

如何使用 Microsoft UI 自动化 select 自定义组合框中的项目?我的 ComboBox 看起来像这样:

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

即我已经用自定义 DataTemplate 覆盖了 ItemTemplate。

但是,现在我无法 select 使用 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;
    }
}

它抛出一个错误,告诉我 SelectionItemPatternIdentifiers.Pattern 是一个不受支持的模式。只有 SynchronizedInputPatternIdentifiers.Pattern 受其试图在 ComboBox 中 select 的元素支持。

我应该如何编写我的 DataTemplate 才能使其 select 可用?

我按以下方式重新定义了我的 ComboBox

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

赋予 TextBlock 与其 Text 值相同的 AutomationProperties.Name 值。

我还将选择 ComboBox 项的函数更新为以下内容:

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

显然,当按原样使用 ComboBox 而不覆盖 ItemTemplate 时,上面的函数会找到它的直接子项,即 ListBoxItem。可以通过 SelectionItemPattern 模式选择 ListBoxItem。但是当覆盖 ItemTemplate 时,该函数反而会找到 TextBlock,它是 ListBoxItem 的子项。因此,我不得不修改我的函数,使其向上遍历,直到找到 ComboBox 的直接子节点并选择它。