首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何定义自定义控件以启用UI自动化和TestStack白色?

如何定义自定义控件以启用UI自动化和TestStack白色?
EN

Stack Overflow用户
提问于 2016-11-06 21:15:48
回答 1查看 3.2K关注 0票数 1

我开始使用TestStack White (UI自动化)来自动化WPF现有应用程序中的测试。当使用标准控件时,一切都很好。但是,在尝试交互自定义控件时,我遇到了一些问题。

例如,我有一个LabeledComboBox,它实际上是一个TextBlock加上一个ComboBox。这被定义为从XAML中的Control +一个ControlTemplate派生的类:

代码语言:javascript
复制
public class LabeledComboBox : Control
{
    static LabeledComboBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(LabeledComboBox), new FrameworkPropertyMetadata(typeof(LabeledComboBox)));
    }
}

代码语言:javascript
复制
<local:LabeledComboBox>
    <local:LabeledComboBox.Template>
         <ControlTemplate TargetType="{x:Type local:LabeledComboBox}">
             <StackPanel>
                  <TextBlock Text="Text"/>
                  <ComboBox/>
             </StackPanel>
          </ControlTemplate>
    </local:LabeledComboBox.Template>
</local:LabeledComboBox>

此控件可以工作,但如果运行UI自动化,则验证UI自动化唯一可见的部分是ComboBox,并且无法访问TextBlock。

但是,如果使用XAML和代码后面的代码将其创建为UserControl,则UI自动化可以正确地看到TextBox和ComboBox。

我试图为我的控件创建一个AutomationPeer (FrameworkElementAutomationPeer),但是到目前为止,我还没有能够使UI自动化中的TextBlock可见。一个有趣的结果是,FrameworkElementAutomationPeer::GetChildrenCore()正确地返回了两个自动化对等点的列表,一个用于TextBlock,一个用于ComboBox。

我应该如何更改我的自定义控件,以便它能够正确地使用UI自动化和白色测试?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-07 07:32:38

TextBlock的默认自动化对等程序(TextBlockAutomationPeer)出于某种原因从UI树中移除相应的所有者(如果它是ControlTemplate的一部分)。

您可以在这里找到相关代码:https://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Automation/Peers/TextBlockAutomationPeer.cs,16e7fab76ffcb40a

代码语言:javascript
复制
 override protected bool IsControlElementCore()
 {
    // Return true if TextBlock is not part of a ControlTemplate
    TextBlock tb = (TextBlock)Owner;
    DependencyObject templatedParent = tb.TemplatedParent;
    return templatedParent == null || templatedParent is ContentPresenter; // If the templatedParent is a ContentPresenter, this TextBlock is generated from a DataTemplate
 }

因此,要解决这个问题,您必须声明TextBlock不是在ControlTemplate中,或者使用这样的代码来解决(很难将其概括为整个应用程序.):

代码语言:javascript
复制
public class LabeledComboBox : Control
{
    static LabeledComboBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(LabeledComboBox), new FrameworkPropertyMetadata(typeof(LabeledComboBox)));
    }

    // define our own peer
    protected override AutomationPeer OnCreateAutomationPeer()
    {
        return new LabeledComboBoxAutomationPeer(this);
    }

    protected class LabeledComboBoxAutomationPeer : FrameworkElementAutomationPeer
    {
        public LabeledComboBoxAutomationPeer(LabeledComboBox owner) : base(owner)
        {
        }

        // replace all TextBlockAutomationPeer by our custom peer for TextBlock
        protected override List<AutomationPeer> GetChildrenCore()
        {
            var list = base.GetChildrenCore();
            for (int i = 0; i < list.Count; i++)
            {
                var tb = list[i] as TextBlockAutomationPeer;
                if (tb != null)
                {
                    list[i] = new InteractiveTextBlockAutomationPeer((TextBlock)tb.Owner);
                }
            }
            return list;
        }
    }

    // just do the default stuff, instead of the strange TextBlockAutomationPeer implementation
    protected class InteractiveTextBlockAutomationPeer : FrameworkElementAutomationPeer
    {
        public InteractiveTextBlockAutomationPeer(TextBlock owner) : base(owner)
        {
        }

        protected override AutomationControlType GetAutomationControlTypeCore()
        {
            return AutomationControlType.Text;
        }

        protected override string GetClassNameCore()
        {
            return "TextBlock";
        }
    }
}

另一种解决方案是创建您自己的TextBlock控件类(从TextBlock派生),并重写OnCreateAutomationPeer以返回自定义的OnCreateAutomationPeer

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40454625

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档