AutomationProperties.AutomationId自定义控件未公开

时间:2015-05-12 17:52:34

标签: c# .net wpf xaml microsoft-ui-automation

我已经对这个问题进行了3天的攻击,但我们还没有找到答案。

我有一个用WPF(dot Net 4.5)编写的应用程序,我正在使用Teststack.White尝试编写一些自动GUI测试用例。开发人员已经为某些控件提供了x:Names,它们通过Inspect / WPF Inspector / Visual UI Automation验证显示为AutomationId就好了。

还有一些其他控件被埋得更深了,我已经负责提供自动化ID(主要是作为练习,所以我可以更熟悉后端)。这就是我一直在反对的事情。

我尝试过为控件提供AutomationProperties.AutomationId(和.Name)属性。我给AutomationProperties一个名称空间定义。我也确保参考了SWA.Peers。

我还没有尝试在XAML中使用属性设置器,因为它们目前没有多大意义,我希望不需要用C#编写内容来设置它们(如果我做,我会做,但只是希望)。

我的一位同事坐下来,我们拿出了没有暴露自动化ID属性的最小设置(不幸的是,他和其他开发人员一直在争论为什么这不是&#39发生了。它看起来像:

MainWindow.xaml:

<Window x:Class="TestAutomationUI.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:autoProp="clr-namespace:System.Windows.Automation;assembly=PresentationCore"
    xmlns:common="clr-namespace:Asi.Ui.Common"
    Title="Test UI (Pick me)" Height="455.075" Width="525">

    <Window.Resources>
        <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/IconLabelButton.xaml" />
        </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <StackPanel x:Name="PresentationRoot">
        <common:IconLabelButton x:Name="TestButton" autoProp:AutomationProperties.AutomationId="TestButtonClick" Text="Stuff" Margin="245,0,214.4,0" RenderTransformOrigin="4.648,0.588" Height="32">
        </common:IconLabelButton>
    </StackPanel>
</Window>

IconLabelButton.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:autoProp="clr-namespace:System.Windows.Automation;assembly=PresentationCore"
                    xmlns:common="clr-namespace:Asi.Ui.Common">

    <Style TargetType="common:IconLabelButton">
        <Setter Property="Template" Value="{DynamicResource Asi.Ui.Common.IconLabelButton}" />
        <Setter Property="IsTabStop" Value="False" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="FontWeight" Value="{DynamicResource Mobius.UI.Resources.Fonts.WeightLight}"/>
        <Setter Property="Spacing" Value="10" />
    </Style>

    <ControlTemplate x:Key="Asi.Ui.Common.IconLabelButton" TargetType="common:IconLabelButton">
        <Border Background="{TemplateBinding Background}" Height="30">
            <Button Style="{DynamicResource Mobius.UI.Resources.Styles.IconButton}" Margin="0" Padding="0" HorizontalContentAlignment="Stretch" HorizontalAlignment="Left"
                    Command="{TemplateBinding Command}" CommandParameter="{TemplateBinding CommandParameter}" Foreground="{TemplateBinding Foreground}">

                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="22" />
                        <ColumnDefinition Width="{TemplateBinding Spacing}" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Grid Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="22" Height="22">
                        <Path Margin="1" Height="20" Width="20" Fill="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ContentControl}}}" Data="{TemplateBinding Icon}" Stretch="Fill"/>
                        <Path Margin="1" Height="20" Width="20" Fill="{TemplateBinding AdornerIconFill}" Data="{TemplateBinding AdornerIcon}" Stretch="Fill"/>
                    </Grid>
                    <TextBlock Grid.Column="2" Text="{TemplateBinding Text}" VerticalAlignment="Center" Foreground="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ContentControl}}}" FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" FontStretch="{TemplateBinding FontStretch}" FontWeight="{TemplateBinding FontWeight}"/>
                </Grid>
            </Button>
        </Border>
    </ControlTemplate>

</ResourceDictionary>

IconLabelButton.xaml.cs:

    using System;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace Asi.Ui.Common
{

    public class IconLabelButton : Control
    {

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(IconLabelButton), new PropertyMetadata(default(string)));

        public static readonly DependencyProperty AdornerIconProperty =
            DependencyProperty.Register("AdornerIcon", typeof(object), typeof(IconLabelButton), new PropertyMetadata(default(object)));

        public static readonly DependencyProperty IconProperty =
            DependencyProperty.Register("Icon", typeof(object), typeof(IconLabelButton), new PropertyMetadata(default(object)));

        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register("Command", typeof(ICommand), typeof(IconLabelButton), new PropertyMetadata(default(ICommand)));

        public static readonly DependencyProperty CommandParameterProperty =
            DependencyProperty.Register("CommandParameter", typeof(object), typeof(IconLabelButton), new PropertyMetadata(default(ICommand)));

        public static readonly DependencyProperty SpacingProperty =
            DependencyProperty.Register("Spacing", typeof(GridLength), typeof(IconLabelButton), new PropertyMetadata(default(GridLength)));

        public static readonly DependencyProperty IconButtonSizeProperty =
            DependencyProperty.Register("IconButtonSize", typeof(GridLength), typeof(IconLabelButton), new PropertyMetadata(default(GridLength)));

        public static readonly DependencyProperty AdornerIconFillProperty =
            DependencyProperty.Register("AdornerIconFill", typeof(Brush), typeof(IconLabelButton), new PropertyMetadata(default(Brush)));


        static IconLabelButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(IconLabelButton), new FrameworkPropertyMetadata(typeof(IconLabelButton)));
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
        public object AdornerIcon
        {
            get { return GetValue(AdornerIconProperty); }
            set { SetValue(AdornerIconProperty, value); }
        }
        public object Icon
        {
            get { return GetValue(IconProperty); }
            set { SetValue(IconProperty, value); }
        }
        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }
        public object CommandParameter
        {
            get { return GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }
        public GridLength Spacing
        {
            get { return (GridLength)GetValue(SpacingProperty); }
            set { SetValue(SpacingProperty, value); }
        }
        public GridLength IconButtonSize
        {
            get { return (GridLength)GetValue(IconButtonSizeProperty); }
            set { SetValue(IconButtonSizeProperty, value); }
        }
        public Brush AdornerIconFill
        {
            get { return (Brush)GetValue(AdornerIconFillProperty); }
            set { SetValue(AdornerIconFillProperty, value); }
        }
    }
}

如果这是一个简单的问题(或者我没有问正确的问题),我道歉。我是一名入门级程序员,只是粗略地熟悉WPF / XAML。

提前感谢您的帮助! (希望它可以轻松解决!)

更新:在进一步挖掘UI自动化提供程序后,看起来必须编写所有自定义控件以支持AutomationProperties。当然,与开发者谈论并非如此。

当我找到解决方案时,我会发布更多信息。

1 个答案:

答案 0 :(得分:4)

您的控件没有AutomationPeer。因此,AutomationId设置不会设置任何内容。

在控件代码隐藏中覆盖OnCreateAutomationPeer,如下所示:

    protected override AutomationPeer OnCreateAutomationPeer()
    {
        return new IconLabelButtonAutomationPeer(this);
    }

你的新IconLabelButtonAutomationPeer看起来像这样:

public class IconLabelButtonAutomationPeer : FrameworkElementAutomationPeer
{
    public IconLabelButtonAutomationPeer(IconLabelButton owner)
        : base(owner)
    {
    }
}
相关问题