代码之家  ›  专栏  ›  技术社区  ›  GraemeF

如何在分组项的WPF ItemsControl上使用UI自动化?

  •  4
  • GraemeF  · 技术社区  · 15 年前

    我正在使用 Microsoft UI Automation AutomationElement )对我的应用程序运行自动验收测试。这进展顺利,但我遇到了一个似乎没有暴露于自动化框架的情况。

    ItemsControl (尽管我可以使用它的一个派生控件,例如。 ListBox CollectionViewSource 对项目进行分组。下面是一个完整的窗口来演示:

    <Window x:Class="GroupAutomation.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Orchestra">
        <Window.Resources>
    
            <!-- Take some simple data -->
            <XmlDataProvider x:Key="SampleData" XPath="Orchestra/Instrument">
                <x:XData>
                    <Orchestra xmlns="">
                        <Instrument Name="Flute" Category="Woodwind" />
                        <Instrument Name="Trombone" Category="Brass" />
                        <Instrument Name="French horn" Category="Brass" />
                    </Orchestra>
                </x:XData>
            </XmlDataProvider>
    
            <!-- Add grouping -->
            <CollectionViewSource Source="{Binding Source={StaticResource SampleData}}" x:Key="GroupedView">
                <CollectionViewSource.GroupDescriptions>
                    <PropertyGroupDescription PropertyName="@Category" />
                </CollectionViewSource.GroupDescriptions>
            </CollectionViewSource>
        </Window.Resources>
    
        <!-- Show it in an ItemsControl -->
        <ItemsControl ItemsSource="{Binding Source={StaticResource GroupedView}}" HorizontalAlignment="Left" Margin="4">
            <ItemsControl.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Path=Name}" FontWeight="Bold" />
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                </GroupStyle>
            </ItemsControl.GroupStyle>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border Padding="4" Margin="4" Background="#FFDEDEDE">
                        <StackPanel>
                            <Label Content="{Binding XPath=@Name}" />
                            <Button Content="Play" />
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Window>
    

    Screenshot of window with a list
    (来源: brizzly.com )

    但是,如果我往里面看 UISpy.exe (或使用 自动化元件

    UISpy
    (来源: brizzly.com )

    是否可以对分组的项使用UI自动化?如果可以,如何使用?

    4 回复  |  直到 5 年前
        1
  •  7
  •   Trasvi    8 年前

    我遇到了这个问题,并通过从 http://www.colinsalmcorner.com/post/genericautomationpeer--helping-the-coded-ui-framework-find-your-custom-controls GroupItem s。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Automation;
    using System.Windows.Automation.Peers;
    using System.Windows.Media;
    using System.Xml;
    
    namespace ClassLibrary1
    {
        public class MyItemsControl : ItemsControl
        {
            protected override AutomationPeer OnCreateAutomationPeer()
            {
                return new GenericAutomationPeer(this);
            }
        }
    
        public class GenericAutomationPeer : UIElementAutomationPeer
        {
            public GenericAutomationPeer(UIElement owner) : base(owner)
            {
            }
    
            protected override List<AutomationPeer> GetChildrenCore()
            {
                var list = base.GetChildrenCore();
                list.AddRange(GetChildPeers(Owner));
                return list;
            }
    
            private List<AutomationPeer> GetChildPeers(UIElement element)
            {
                var list = new List<AutomationPeer>();
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
                {
                    var child = VisualTreeHelper.GetChild(element, i) as UIElement;
                    if (child != null)
                    {
                        AutomationPeer childPeer;
                        if (child is GroupItem)
                        {
                            childPeer = new GenericAutomationPeer(child);
                        }
                        else
                        {
                            childPeer = UIElementAutomationPeer.CreatePeerForElement(child);
                        }
                        if (childPeer != null)
                        {
                            list.Add(childPeer);
                        }
                        else
                        {
                            list.AddRange(GetChildPeers(child));
                        }
                    }
                }
                return list;
            }
        }
    
    }
    

    我希望这能帮助那些还在寻找答案的人!

        2
  •  3
  •   Orion Edwards    15 年前

    我不是百分之百肯定纽扣,但是 TextBlock 内部的控件 DataTemplate 是的 进入UI自动化树。显然,这是一个优化,以避免1000的不必要的文本块。

    public class AutomatableTextBlock : TextBlock
    {
        protected override AutomationPeer OnCreateAutomationPeer()
        {
            return new AutomatableTextBlockAutomationPeer(this);
        }
    
        class AutomatableTextBlockAutomationPeer : TextBlockAutomationPeer
        {
            public AutomatableTextBlockAutomationPeer(TextBlock owner)
                : base(owner)
            { }
    
            protected override bool IsControlElementCore()
            { return true; }
        }
    }
    

    注意:UI自动化也不会公开其他各种控件,比如 Canvas , Panel

    我不知道为什么 Button 没有出现。。。。嗯

        3
  •  2
  •   mdonoughe    13 年前

    我在应用程序中使用 TreeWalker.RawViewWalker 使用后手动导航树 AutomationElement.FindFirst 找到模板。 FindFirst 在自动化其他人的应用程序时,似乎可靠地排除了所有需要的信息。 RawViewWalker 当元素出现在“Inspect Objects”中时似乎可以工作,但在UISpy或您的应用程序中则不行。

        4
  •  1
  •   Tim Cooper    13 年前

    您使用什么工具来编写自动脚本?我本以为有一个选项可以钻取WPF的逻辑/可视化树,而不是依赖Win32树(UISpy所展示的)。

    如果您使用 Snoop