3

我們的應用程序有一個畫布,這是我們添加繪圖視覺效果(如線,多邊形等)如何識別UIAutomation中的WPF繪圖畫面?

// sample code 

var canvas = new Canvas(); // create canvas 
var visuals = new VisualCollection(canvas); // link the canvas to the visual collection 
visuals.Add(new DrawingVisual()); // add the visuals to the canvas 
visuals.Add(new DrawingVisual()); 

我們的目標是通過自動化這些視覺效果添加到畫布和驗證他們適當增加。我們使用基於微軟UIAutomation的框架。

當使用「Inspect」等工具檢查視覺結構時,我找不到畫布。做了一些調查並發現您需要覆蓋UIElement中的OnCreateAutomationPeer方法,並返回適用的AutomationPeer對象,以便能夠在自動化中看到該方法。

作出了改變,現在我可以看到畫布,但是我仍然無法看到畫布下添加的任何視覺效果。

任何人都可以幫我理解這個問題是什麼?

事情試圖/替代品:

  1. 試圖聘請OnCreateAutomationPeer技術,但 DrawingVisual小號不從UIElement派生,我不能添加UIElement小號 到Canvas.VisualCollection
  2. 圖像識別是一個選項,但我們 試圖避免它出於性能/維護考慮。

回答

4

只有UIElement可以從UI自動化中看到(就像你看到的,OnCreateAutomationPeer從這個類開始,而不是從Visual類開始)。

所以你需要添加UIElement(或派生像FrameworkElement)到畫布,如果你想它可以被UIAutomation使用。

您可以創建自己的類喜歡這裏描述:Using DrawingVisual Objects或自定義用戶控件或使用現有的一個適合您的需要,但它必須莫名其妙的UIElement派生。

一旦你有一個好的類,你可以使用默認的AutomationPeer或重寫該方法並進行更加緊密的調整。

如果你想保留Visual對象,一種解決方法是修改包含對象(但它仍然需要從UIElement派生)。例如,在這裏,如果我按照該鏈接的文章中,我可以寫一個包含對象的自定義(而不是你的示例代碼畫布,所以你可能需要稍微適應)是這樣的:

public class MyVisualHost : UIElement 
{ 
    public MyVisualHost() 
    { 
     Children = new VisualCollection(this); 
    } 

    public VisualCollection Children { get; private set; } 


    public void AddChild(Visual visual) 
    { 
     Children.Add(visual); 
    } 

    protected override int VisualChildrenCount 
    { 
     get { return Children.Count; } 
    } 

    protected override Visual GetVisualChild(int index) 
    { 
     return Children[index]; 
    } 

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

    // create a custom AutomationPeer for the container 
    private class MyVisualHostPeer : UIElementAutomationPeer 
    { 
     public MyVisualHostPeer(MyVisualHost owner) 
      : base(owner) 
     { 
     } 

     public new MyVisualHost Owner 
     { 
      get 
      { 
       return (MyVisualHost)base.Owner; 
      } 
     } 

     // a listening client (like UISpy is requesting a list of children) 
     protected override List<AutomationPeer> GetChildrenCore() 
     { 
      List<AutomationPeer> list = new List<AutomationPeer>(); 
      foreach (Visual visual in Owner.Children) 
      { 
       list.Add(new MyVisualPeer(visual)); 
      } 
      return list; 
     } 
    } 

    // create a custom AutomationPeer for the visuals 
    private class MyVisualPeer : AutomationPeer 
    { 
     public MyVisualPeer(Visual visual) 
     { 
     } 

     // here you'll need to implement the abstrat class the way you want 
    } 
} 
+0

感謝您的答覆西蒙。在畫布上使用DrawingVisual而不是UIElements是有意識地幫助表演的決定。我們的應用程序有一個噸形狀添加到畫布。我想知道是否有另一種解決方法。 – Schu 2014-10-02 12:53:36

+1

@Schu - 我已經更新了我的答案。 – 2014-10-02 14:15:01

+0

再次感謝西蒙。這應該工作。我有類似的東西,我在OnCreateAutomationPeer內部傳遞視覺效果,並試圖跟上視覺集合的變化,並且在那裏停留。您通過在所有者下添加的Children屬性解決了該問題。 – Schu 2014-10-02 17:43:43