4

アプリケーションにはキャンバスがあり、そこに描画ビジュアル (線、ポリゴンなど) を追加します。

// 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());

私たちの目標は、自動化によってこれらのビジュアルをキャンバスに追加し、それらが適切に追加されていることを検証することです。Microsoft の UIAutomation に基づくフレームワークを使用します。

「検査」などのツールを使用して視覚構造を検査すると、キャンバスが見つかりませんでした。いくつかの調査を行い、自動化でそれを確認できるようにするには、OnCreateAutomationPeerからメソッドをオーバーライドし、UIElement適切なオブジェクトを返す必要があることがわかりました。AutomationPeer

変更を行い、キャンバスが表示されるようになりましたが、キャンバスの下に追加されたビジュアルはまだ表示されません。

問題が何であるかを理解するのを手伝ってくれる人はいますか?

試したこと/代替案:

  1. OnCreateAutomationPeer 手法を採用しようとしましたが、 DrawingVisualから派生したものではなく、 に sをUIElement追加できません。UIElementCanvas.VisualCollection
  2. 画像認識はオプションですが、パフォーマンス/メンテナンスを考慮して回避しようとしています。
4

1 に答える 1

5

UI オートメーションからは UIElement のみが表示されます (ご覧のとおり、OnCreateAutomationPeer は Visual クラスからではなく、このクラスから開始されます)。

したがって、UIAutomation で使用できるようにする場合は、キャンバスに UIElement (または FrameworkElement のように派生) を追加する必要があります。

ここで説明されているように、独自のクラスを作成できます: DrawingVisual オブジェクトを使用するか、カスタム UserControl を使用するか、必要に応じて既存のクラスを使用しますが、何らかの方法で UIElement から派生させる必要があります。

適切なクラスができたら、デフォルトの AutomationPeer を使用するか、メソッドをオーバーライドして、より密接に適応させることができます。

Visual オブジェクトを保持したい場合、1 つの解決策は、含まれているオブジェクトを変更することです (ただし、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
    }
}
于 2014-10-02T06:46:40.557 に答える