2010-05-05 28 views
4

我使用Microsoft UI Automation(即AutomationElement)對我的應用程序進行自動驗收測試。這個過程很順利,但是我遇到了一個似乎並未暴露於自動化框架的情況。如何在對項目進行分組的WPF ItemsControl上使用UI自動化?

我有一個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 [email protected]}" /> 
         <Button Content="Play" /> 
        </StackPanel> 
       </Border> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</Window> 

這會產生含有分爲其類別的商品的窗口,並且每個項目都有一個按鈕,我想點擊與UI自動化:

Screenshot of window with a list http://pics.brizzly.com/thumb_lg_2C45.jpg

但是,如果我看着UISpy.exe(或AutomationElement導航),我只看到了組(甚至在原始視圖):

UISpy http://pics.brizzly.com/thumb_lg_2C47.jpg

正如你所看到的,這些組在那裏,但它們不包含任何項目,所以無處尋找按鈕。我已經在WPF 3.5 SP1和WPF 4.0中嘗試了這一點,並得到相同的結果。

是否可以在分組的項目上使用UI自動化,如果是這樣,如何?

+0

直接使用項目控制項目,如下所示。 [link](http://abusanad.net/2016/12/19/wpf-itemscontrol-with-teststack-white/) – user1912383 2016-12-19 21:15:16

回答

1

你用什麼工具編寫自動腳本?我原以爲會有一個選項可以深入到WPF的邏輯/視覺樹中,而不是依賴於Win32樹(如UISpy所示)。

如果您使用Snoop查看相同的應用程序,您將看到完整的可視化和邏輯樹。

+0

我正在使用MbUnit編寫驗收測試(但可能是NUnit,xUnit.NET或其他)並使用UI自動化框架驅動應用程序。通過處理用戶可以看到和/或與之交互的UI項目,而不是直接查看WPF樹,從而將測試從實現中分離出來(在某種程度上)。我已經這樣做了大約一年,這是我發現的第一個案例「不工作」,所以我希望能夠填補這個空白,而不是在這個階段切換框架。 – GraemeF 2010-05-06 11:21:18

2

我不是百分之百確定按鈕,但TextBlock控件是在DataTemplate s做而不是得到放入UI自動化樹。顯然這是一個優化,以避免1000多個不必要的文本塊。

您可以通過SubClassing TextBlock解決此問題。這裏是我的:

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自動化還沒有公開的各種其他控件像CanvasPanel,你可以讓他們有類似的子類出現。

在說,我不知道爲什麼Button沒有出現.... Hrmmm

+0

如果分組被禁用,我需要的元素會顯示出來,所以我不認爲你的答案有助於我感到害怕。我在示例中使用了一個按鈕,因爲它們總是顯示出來(除非在這種情況下!)。 – GraemeF 2010-05-17 12:04:49

2

我結束了使用TreeWalker.RawViewWalker使用AutomationElement.FindFirst找到後手動導航樹解決這個在我的應用程序模板。當自動化別人的應用程序時,FindFirst似乎可靠地排除了所有您想要的信息。 RawViewWalker似乎在元素顯示在「檢查對象」中,但在UISpy或您的應用程序中不起作用。

+0

它的工作!有趣的是,UISpy在一臺計算機上找不到子節點,但在另一臺計算機上找到了。兩臺電腦都有相同的規格和相同的軟件安裝。無論如何,TreeWalker的訣竅都適用於這兩者。 – SlavaGu 2013-03-12 04:09:56

3

我遇到了這個問題,並設法通過從http://www.colinsalmcorner.com/post/genericautomationpeer--helping-the-coded-ui-framework-find-your-custom-controls實施'GenericAutomationPeer'併爲GroupItem添加特殊情況來解決此問題。

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

} 

我希望這可以幫助任何人仍然在尋找答案!

+0

這並不理想,但考慮到爲分組ItemsControls修復AutomationPeer的努力,這是一個非常有效的解決方法。謝謝! – 2016-11-10 14:40:38

相關問題