C# 使用UI自动化订阅组合框选择更改事件

C# 使用UI自动化订阅组合框选择更改事件,c#,automation,ui-automation,microsoft-ui-automation,C#,Automation,Ui Automation,Microsoft Ui Automation,我是UI自动化方面的新手。 有一个ComboBox类型的AutomationElement。 我正在寻找一种订阅当组合框更改其名称属性时引发的事件的方法 这就是我试图做的,但它不起作用: Automation.AddAutomationPropertyChangedEventHandler( elementComboBox, TreeScope.Element, new AutomationPropertyChangedEventHandler(OnUIAutomatio

我是UI自动化方面的新手。
有一个ComboBox类型的AutomationElement。
我正在寻找一种订阅当组合框更改其
名称
属性时引发的事件的方法

这就是我试图做的,但它不起作用:

Automation.AddAutomationPropertyChangedEventHandler(
    elementComboBox,
    TreeScope.Element,
    new AutomationPropertyChangedEventHandler(OnUIAutomationPropChanged),
    NameProperty
);

看起来您已经知道如何访问ComboBox元素,所以我们只需设置一个用于检测更改事件的

组合框控件是由以下内容组成的合成对象:

  • 外部容器
  • 用于输入选择/搜索值的内部编辑控件,当组合框为下拉类型时可用
  • 内部ListControl,用于显示ComboBox中包含的项目列表,显示为ComboBox下拉元素的一个图标
项目选择属于ListControl,我们需要从该控件获取值。
支持。
方法返回
列表项
元素的集合:项的
名称
属性返回当前选择值

通过AutomationElement识别感兴趣的组合框,何时可以为其
ExpandCollapseState
属性更改设置事件处理程序,如下所示:

bool success = SetExpandCollapseEventHandler(elementComboBox);
// [...]
// Remove the handler when you're done with it
RemoveExpandCollapseEventHandler(elementComboBox);
此处,
string selectedValue
包含组合框关闭时选择的值:
当然,您可以在ExpandCollapseState是
展开的
合并的
时读取该值,以比较当前值和所选值


► 订阅的:

如果您需要知道在没有使用GUI进行实际用户选择的情况下何时更改/选择组合框列表的任何元素,则可以订阅由
列表的子元素引发的事件。
您只需要一个附加到更大范围的处理程序:
TreeScope.Children

警告:由于这些事件需要异步处理,因此会在线程池线程中引发这些事件

这会产生以下后果:

  • 无法直接访问UI线程中的控件(需要
    BeginInvoke()
  • 如果/当ComboBox控件被释放(例如,当父窗口关闭时),您必须删除
    自动venthandler
    ,否则您的应用程序将变得不稳定,并且可能会永久性地等待事件从某个元素返回值,而该元素在某一点上不再响应
您可能希望在父窗口关闭时使用处理程序接收通知,然后调用
Automation.RemoveAutomationEventHandler
(如图所示),但也可能(根据操作的上下文进行评估)调用该方法

称为:

bool success = SetListItemChangedEventHandler(elementComboBox);
// [...]
// Remove the handler when you're done with it
RemoveListItemChangedHandler();


谢谢当组合框折叠/展开时,您的解决方案非常有效。但是当组合框从外部更改时,事件不会引发。在我的例子中,当用户在另一个控件中选择某些元素时,combobox的项目从外部更改(实际上是在3D空间中,但这并不重要)。每次更改三维空间中的选择时,组合框的项目列表和选定元素也会更改。我需要订阅任何可能通知组合框更改的事件。好吧,您在问题中没有描述任何这些。编辑问题并添加理解场景所需的所有细节。不知道3D空间意味着什么。无论如何,您可能只想订阅ListControl的事件,而不是ComboBox本身(如前所述,ComboBox是一个复合控件)。我添加了一个与List元素的ListItems选择事件相关的部分。Jimi!谢谢你这么详细的回答。这对我很有用。我会尽快在问题中补充资料
bool success = SetListItemChangedEventHandler(elementComboBox);
// [...]
// Remove the handler when you're done with it
RemoveListItemChangedHandler();
private AutomationElement listElement = null;
private AutomationEventHandler ListItemChangedHandler = null;

public bool SetListItemChangedEventHandler(AutomationElement combobox)
{
    listElement = combobox.FindFirst(TreeScope.Children,
        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.List));

    if ((bool)listElement.GetCurrentPropertyValue(AutomationElement.IsSelectionPatternAvailableProperty)) {
        Automation.AddAutomationEventHandler(SelectionItemPattern.ElementSelectedEvent, 
            listElement, TreeScope.Children, 
            ListItemChangedHandler = new AutomationEventHandler(OnListItemChanged));

        return true;
    }
    return false;
}
        
private void OnListItemChanged(object elm, AutomationEventArgs e)
{
    string selectedValue = (elm as AutomationElement)?.Current.Name;
}

private void RemoveListItemChangedHandler()
{
    Automation.RemoveAutomationEventHandler(
        SelectionItemPattern.ElementSelectedEvent, listElement, ListItemChangedHandler);
    ListItemChangedHandler = null;
}