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 的框架。

当使用像“检查”这样的工具来检查视觉结构时,我找不到画布。做了一些研究并发现您需要覆盖OnCreateAutomationPeerfrom 的方法UIElement,并返回适用AutomationPeer的对象才能能够在自动化中看到它。

进行了更改,现在我可以看到画布,但是我仍然看不到画布下添加的任何视觉效果。

谁能帮我理解问题是什么?

尝试过的事情/替代方案:

  1. 尝试使用 OnCreateAutomationPeer 技术,但 DrawingVisuals 不派生自UIElement,并且我无法将UIElements 添加到Canvas.VisualCollection.
  2. 图像识别是一种选择,但出于性能/维护方面的考虑,我们试图避免使用它。
4

1 回答 1

5

从 UI 自动化中只能看到 UIElement(就像您所看到的,OnCreateAutomationPeer 从此类开始,而不是从 Visual 类开始)。

因此,如果您希望 UIAutomation 可以使用它,则需要将 UIElement(或类似 FrameworkElement 的派生对象)添加到画布。

您可以创建自己的类,如下所述:Using DrawingVisual Objects or with a custom UserControl 或使用适合您需要的现有类,但它必须以某种方式从 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
    }
}
于 2014-10-02T06:46:40.557 回答