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