カスタム オートメーション ピア

Microsoft UI オートメーション のオートメーション ピアの概念と、独自のカスタム UI クラスのオートメーション サポートを提供する方法について説明します。

UI オートメーションは、オートメーション クライアントがさまざまな UI プラットフォームとフレームワークのユーザー インターフェイスを調べたり操作したりするために使用できるフレームワークを提供します。 Windows アプリを作成している場合は、UI に使用するクラスによって UI オートメーション サポートが既に提供されています。 既存の非シール クラスから派生して、新しい種類の UI コントロールまたはサポート クラスを定義できます。 その過程で、クラスはアクセシビリティサポートを必要とする動作を追加する可能性がありますが、既定のUI オートメーションサポートでは対応していません。 この場合、基本実装で使った AutomationPeer クラスから派生し、必要なサポートをピア実装に追加した後、Windows アプリ コントロールのインフラストラクチャに、新しいピアを作成する必要があることを通知することによって、既存の UI オートメーション サポートを拡張する必要があります。

UI オートメーションを使用すると、アクセシビリティ アプリケーションやスクリーン リーダーなどの支援技術だけでなく、品質保証 (テスト) コードも有効になります。 どちらのシナリオでも、UI オートメーションクライアントはユーザー インターフェイス要素を調べ、アプリ外の他のコードからアプリとのユーザー操作をシミュレートできます。 すべてのプラットフォームにわたるUI オートメーションとその広い意味については、「UI オートメーションの概要を参照してください。

UI オートメーション フレームワークを使用する対象ユーザーは 2 つあります。

  • UI オートメーション clientsUI オートメーション API を呼び出して、ユーザーに現在表示されているすべての UI について学習します。 たとえば、スクリーン リーダーなどの支援技術は、UI オートメーション クライアントとして機能します。 UI は、関連するオートメーション要素のツリーとして表示されます。 UI オートメーション クライアントは、一度に 1 つのアプリ、またはツリー全体に関心がある場合があります。 UI オートメーション クライアントでは、UI オートメーション API を使用してツリー内を移動したり、オートメーション要素の情報を読み取ったり変更したりすることができます。
  • UI オートメーション providersアプリの一部として導入された UI の要素を公開する API を実装することで、UI オートメーション ツリーに情報を提供します。 新しいコントロールを作成するときに、UI オートメーション プロバイダーシナリオの参加者として機能する必要があります。 プロバイダーとして、すべてのUI オートメーション クライアントがUI オートメーション フレームワークを使用して、アクセシビリティとテストの両方の目的でコントロールと対話できることを確認する必要があります。

通常、UI オートメーション フレームワークには並列 API があります。1 つは UI オートメーション クライアント用の API、もう 1 つは UI オートメーション プロバイダー用の API です。 ほとんどの場合、このトピックでは、UI オートメーション プロバイダーの API、具体的には、その UI フレームワークでプロバイダーの拡張性を有効にするクラスとインターフェイスについて説明します。 場合によっては、UI オートメーション クライアントが使用UI オートメーション API について説明したり、何らかの観点を提供したり、クライアント API とプロバイダー API を関連付ける参照テーブルを提供したりすることがあります。 クライアントの観点の詳細については、「UI オートメーション クライアント プログラマ ガイドを参照してください。

Note

UI オートメーションクライアントは通常、マネージド コードを使用せず、通常は UWP アプリとして実装されません (通常はデスクトップ アプリです)。 UI オートメーションは標準に基づいており、特定の実装やフレームワークではありません。 スクリーン リーダーなどの支援技術製品を含む既存のUI オートメーション クライアントの多くは、コンポーネント オブジェクト モデル (COM) インターフェイスを使用して、UI オートメーション、システム、子ウィンドウで実行されるアプリと対話します。 COM インターフェイスの詳細と、COM を使用してUI オートメーション クライアントを記述する方法については、「UI オートメーションの基礎を参照してください。

カスタム UI クラスのサポートの既存の状態UI オートメーション決定する

カスタム コントロールのオートメーション ピアを実装する前に、基本クラスとそのオートメーション ピアが、必要なアクセシビリティまたはオートメーションのサポートを既に提供しているかどうかをテストする必要があります。 多くの場合、 FrameworkElementAutomationPeer 実装、特定のピア、および実装するパターンを組み合わせることで、基本的で満足できるアクセシビリティ エクスペリエンスを提供できます。 これが正しいかどうかは、コントロールに対するオブジェクト モデルの露出に対する変更の数と基底クラスによって異なります。 また、これは、基底クラスの機能への追加が、テンプレート コントラクト内の新しい UI 要素とコントロールの視覚的な外観のどちらに関連しているかによって異なります。 変更によって、追加のアクセシビリティ サポートが必要なユーザー エクスペリエンスの新しい側面が生じる場合があります。

既存の基本ピア クラスを使用して基本的なアクセシビリティサポートを提供する場合でも、ピアを定義して、自動化されたテスト シナリオのUI オートメーションに正確な ClassName 情報を報告できるようにすることをお勧めします。 この考慮事項は、サードパーティの使用を目的としたコントロールを作成する場合に特に重要です。

オートメーション ピア クラス

UWP は、Windows フォーム、Windows Presentation Foundation (WPF)、Microsoft Silverlight などの以前のマネージド コード UI フレームワークで使用されていた既存のUI オートメーション手法と規則に基づいています。 コントロール クラスとその関数と目的の多くは、以前の UI フレームワークでもその起源を持っています。

規則上、ピア クラス名は、コントロールのクラス名で始まり、"AutomationPeer" で終わります。 たとえば、 ButtonAutomationPeer は、 Button コントロール クラスのピア クラスです。

Note

このトピックでは、アクセシビリティに関連するプロパティを、コントロール ピアを実装する際のより重要なものとして扱います。 ただし、UI オートメーションサポートのより一般的な概念については、UI オートメーション プロバイダー プログラマー ガイドおよびUI オートメーションの基礎に記載されている推奨事項に従ってピアを実装する必要があります。 これらのトピックでは、UI オートメーションの UWP フレームワークで情報を提供するために使用する特定の AutomationPeer API については説明しませんが、クラスを識別したり、他の情報や対話を提供したりするプロパティについて説明します。

ピア、パターン、およびコントロールの種類

コントロール パターンは、コントロールの機能の特定の側面をUI オートメーション クライアントに公開するインターフェイス実装です。 UI オートメーションクライアントは、コントロール パターンによって公開されるプロパティとメソッドを使用して、コントロールの機能に関する情報を取得したり、実行時にコントロールの動作を操作したりします。

コントロール パターンは、コントロール型や外観に関係なく、コントロールの機能を分類したり公開したりするための手段です。 たとえば、表形式インターフェイスを表示するコントロールは、Grid コントロール パターンを使用して、テーブル内の行と列の数を公開し、UI オートメーション クライアントがテーブルから項目を取得できるようにします。 他の例として、UI オートメーション クライアントは、ボタンなどの呼び出し可能なコントロールに対して Invoke コントロール パターンを使用できます。また、リスト ボックス、リスト ビュー、コンボ ボックスなどのスクロール バーがあるコントロールには Scroll コントロール パターンを使用できます。 各コントロール パターンは個別の種類の機能を表し、コントロール パターンを組み合わせて、特定のコントロールでサポートされる機能の完全なセットを記述できます。

コントロール パターンは、インターフェイスが COM オブジェクトに関連する UI に関連します。 COM では、サポートしているインターフェイスをオブジェクトに問い合わせて、それらのインターフェイスを使って機能にアクセスできます。 UI オートメーションでは、UI オートメーションクライアントは、UI オートメーション要素に対してクエリを実行して、サポートされているコントロール パターンを調べた後、サポートされているコントロール パターンによって公開されるプロパティ、メソッド、イベント、および構造体を介して要素とそのピアリングされたコントロールと対話できます。

オートメーション ピアの主な目的の 1 つは、UI 要素がそのピアを介してサポートできる制御パターンをUI オートメーション クライアントに報告することです。 これを行うために、UI オートメーション プロバイダーは、GetPattern メソッドの動作を変更する新しいピアGetPatternCore メソッドをオーバーライドして実装します。 UI オートメーション クライアントは、UI オートメーション プロバイダーが呼び出し元の GetPattern にマップする呼び出しを行います。 UI オートメーションクライアントは、対話する特定のパターンごとにクエリを実行します。 ピアがパターンをサポートしている場合は、それ自体へのオブジェクト参照を返します。それ以外の場合は、 null を返します。 戻り値が null でない場合、UI オートメーション クライアントは、そのコントロール パターンと対話するために、パターン インターフェイスの API をクライアントとして呼び出すことができると想定します。

control 型は、ピアが表すコントロールの機能を広く定義する方法です。 これはコントロール パターンとは異なる概念です。これは、取得できる情報や特定のインターフェイスを介して実行できるアクションUI オートメーションパターンによって通知されるのに対し、コントロール型はその 1 レベル上に存在するためです。 各コントロールの種類には、UI オートメーションのこれらの側面に関するガイダンスがあります。

  • UI オートメーションコントロール パターン: コントロールの種類は複数のパターンをサポートする場合があり、それぞれが情報または相互作用の異なる分類を表します。 各コントロールの種類には、コントロールがサポートする必要がある一連のコントロール パターン、オプションのセット、およびコントロールがサポートしてはならないセットがあります。
  • UI オートメーションプロパティ値: 各コントロールの種類には、コントロールがサポートする必要があるプロパティのセットがあります。 これらは、パターン固有のプロパティではなく、「UI オートメーション プロパティの概要」で説明されている一般的なプロパティです。
  • UI オートメーション イベント: 各コントロールの種類には、コントロールがサポートする必要がある一連のイベントがあります。 ここでも、「UI オートメーション イベントの概要で説明されているように、これらはパターン固有ではなく一般的です。
  • UI オートメーション ツリー構造: 各コントロールの種類は、UI オートメーション ツリー構造でのコントロールの表示方法を定義します。

フレームワークのオートメーション ピアの実装方法に関係なく、UI オートメーション クライアントの機能は UWP に関連付けられません。実際には、支援テクノロジなどの既存のUI オートメーション クライアントが COM などの他のプログラミング モデルを使用する可能性があります。 COM では、クライアントは、要求されたパターンを実装する COM コントロール パターン インターフェイスまたはプロパティ、イベント、またはツリー検査用の一般的なUI オートメーション フレームワークにQueryInterface を使用できます。 パターンの場合、UI オートメーション フレームワークは、そのインターフェイス コードを、アプリのUI オートメーション プロバイダーと関連するピアに対して実行される UWP コードにマーシャリングします。

C# または Microsoft Visual Basic を使った UWP アプリなど、マネージド コード フレームワークのコントロール パターンを実装すると、COM インターフェイスの表現ではなく、.NET Framework インターフェイスを使ってこれらのパターンを表すことができます。 たとえば、Invoke パターンの Microsoft .NET プロバイダー実装のUI オートメーション パターン インターフェイスは、IInvokeProvider です。

コントロール パターン、プロバイダー インターフェイス、およびその目的の一覧については、「 Control パターンとインターフェイスを参照してください。 コントロールの種類の一覧については、「コントロールの種類の概要UI オートメーションを参照してください。

コントロール パターンを実装する方法のガイダンス

コントロール パターンとその目的は、UI オートメーション フレームワークのより大きな定義の一部であり、UWP アプリのアクセシビリティ サポートに適用されるだけではありません。 コントロール パターンを実装するときは、これらのドキュメントに記載されているガイダンスに従って実装する必要があります。ガイダンスは UI オートメーション仕様にも含まれています。 ガイダンスを確認する場合、通常は Microsoft ドキュメントを使うことができます。仕様を参照する必要はありません。 各パターンのガイダンスについては、UI オートメーションコントロール パターンの実装を参照してください。 この領域の各トピックには、"実装ガイドラインと規則" セクションと "必須メンバー" セクションがあります。 このガイダンスでは、通常、 Control Pattern Interfaces for Providers リファレンスの関連するコントロール パターン インターフェイスの特定の API を参照します。 これらのインターフェイスはネイティブ/COM インターフェイスです (また、それらの API では COM スタイルの構文が使用されます)。 ただし、表示される内容はすべて、 Windows.UI.Xaml.Automation.Provider 名前空間に相当します。

既定のオートメーション ピアを使用し、その動作を拡張している場合、これらのピアは既にUI オートメーションガイドラインに準拠して記述されています。 コントロール パターンがサポートされている場合は、「コントロール パターンの実装」のガイダンスに従って、そのパターンサポートUI オートメーション利用できます。 コントロール ピアが、UI オートメーション によって定義されたコントロール型の代表であると報告した場合は、「Supporting UI オートメーション コントロール型に関するページに記載されているガイダンスに従っています。

ただし、ピア実装のUI オートメーションの推奨事項に従うために、コントロール パターンまたはコントロールの種類に関する追加のガイダンスが必要になる場合があります。 これは、UWP コントロールの既定の実装としてまだ存在しないパターンまたはコントロール型のサポートを実装している場合に特に当てはまります。 たとえば、注釈のパターンは、既定のどの XAML コントロールにも実装されていません。 ただし、注釈を広範囲に使用するアプリがあるため、その機能にアクセスできるようにする必要がある場合があります。 このシナリオでは、ピアは IAnnotationProvider を実装する必要がありドキュメントが注釈をサポートしていることを示す適切なプロパティを持つ Document コントロール型として報告する必要があります。

コントロール パターンの実装」のパターンに関 UI オートメーションするガイダンスを使用することをお勧めしますUI オートメーション コントロール型のサポートの下にあるコントロールの種類は、向きと一般的なガイダンスとして使用してください。 API の目的に関する説明や解説については、API リンクの一部に従ってみてください。 ただし、UWP アプリのプログラミングに必要な構文の詳細については、 Windows.UI.Xaml.Automation.Provider 名前空間内で同等の API を見つけ詳細については、これらの参照ページを使用してください。

組み込みのオートメーション ピア クラス

一般に、要素は、ユーザーからの UI アクティビティを受け入れる場合、またはアプリの対話型または意味のある UI を表す支援技術のユーザーが必要とする情報が含まれている場合に、オートメーション ピア クラスを実装します。 すべての UWP ビジュアル要素にオートメーション ピアがあるわけではありません。 オートメーション ピアを実装するクラスの例として、 Button および TextBox があります。 オートメーション ピアを実装しないクラスの例としては、Border や、GridCanvas などの Panel に基づくクラスがあります。 Panelは、ビジュアルのみのレイアウト動作を提供しているため、ピアがありません。 ユーザーが Panel を操作するためのアクセシビリティ関連の方法はありません。 Panelに含まれる子要素は、代わりに、ピアまたは要素表現を持つツリー内の次に使用可能な親の子要素として、UI オートメーション ツリーに報告されます。

UI オートメーションと UWP プロセスの境界

通常、UWP アプリUI オートメーションアクセスするクライアント コードは、アウトプロセスで実行されます。 UI オートメーション フレームワーク インフラストラクチャを使用すると、プロセス境界を越えて情報を取得できます。 この概念については、UI オートメーションの基礎で詳しく説明します。

OnCreateAutomationPeer

UIElement から派生するすべてのクラスには、保護された仮想メソッド OnCreateAutomationPeerが含まれています。 オートメーション ピアのオブジェクト初期化シーケンスは、OnCreateAutomationPeer を呼び出して各コントロールのオートメーション ピア オブジェクトを取得するため、実行時に使用するUI オートメーション ツリーを構築します。 UI オートメーションコードでは、ピアを使用してコントロールの特性と機能に関する情報を取得し、コントロール パターンを使用して対話型の使用をシミュレートできます。 オートメーションをサポートするカスタム コントロールは、 OnCreateAutomationPeer をオーバーライドし、 AutomationPeer から派生するクラスのインスタンスを返す必要があります。 たとえば、カスタム コントロールが ButtonBase クラスから派生している場合、 OnCreateAutomationPeer によって返されるオブジェクトは、 ButtonBaseAutomationPeer から派生する必要があります。

カスタム コントロール クラスを記述していて、新しいオートメーション ピアも指定する場合は、カスタム コントロールの OnCreateAutomationPeer メソッドをオーバーライドして、ピアの新しいインスタンスを返すようにする必要があります。 ピア クラスは、 AutomationPeer から直接または間接的に派生する必要があります。

たとえば、次のコードでは、カスタム コントロールNumericUpDownUI オートメーション目的でピア NumericUpDownPeerを使用する必要があることを宣言しています。

using Windows.UI.Xaml.Automation.Peers;
...
public class NumericUpDown : RangeBase {
    public NumericUpDown() {
    // other initialization; DefaultStyleKey etc.
    }
    ...
    protected override AutomationPeer OnCreateAutomationPeer()
    {
        return new NumericUpDownAutomationPeer(this);
    }
}
Public Class NumericUpDown
    Inherits RangeBase
    ' other initialization; DefaultStyleKey etc.
       Public Sub New()
       End Sub
       Protected Overrides Function OnCreateAutomationPeer() As AutomationPeer
              Return New NumericUpDownAutomationPeer(Me)
       End Function
End Class
// NumericUpDown.idl
namespace MyNamespace
{
    runtimeclass NumericUpDown : Windows.UI.Xaml.Controls.Primitives.RangeBase
    {
        NumericUpDown();
        Int32 MyProperty;
    }
}

// NumericUpDown.h
...
struct NumericUpDown : NumericUpDownT<NumericUpDown>
{
	...
    Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer()
    {
        return winrt::make<MyNamespace::implementation::NumericUpDownAutomationPeer>(*this);
    }
};
//.h
public ref class NumericUpDown sealed : Windows::UI::Xaml::Controls::Primitives::RangeBase
{
// other initialization not shown
protected:
    virtual AutomationPeer^ OnCreateAutomationPeer() override
    {
         return ref new NumericUpDownAutomationPeer(this);
    }
};

Note

OnCreateAutomationPeer実装では、カスタム オートメーション ピアの新しいインスタンスを初期化し、呼び出し元のコントロールを所有者として渡して、そのインスタンスを返す以外に何もしないでください。 このメソッドで追加のロジックを試みないでください。 特に、同じ呼び出し内で AutomationPeer の破棄につながる可能性のあるロジックは、予期しないランタイム動作を引き起こす可能性があります。

OnCreateAutomationPeerの一般的な実装では、メソッドのオーバーライドがコントロール クラス定義の残りの部分と同じスコープ内にあるため、ownerthis または Me として指定されます。

実際のピア クラス定義は、コントロールと同じコード ファイルまたは別のコード ファイルで実行できます。 ピア定義はすべて、 Windows.UI.Xaml.Automation.Peers 名前空間に存在します。これは、ピアが提供するコントロールとは別の名前空間です。 OnCreateAutomationPeer メソッド呼び出しに必要な名前空間を参照する限り、ピアを個別の名前空間で宣言することもできます。

正しいピア 基底クラスの選択

AutomationPeer が、派生元のコントロール クラスの既存のピア ロジックに最適な基底クラスから派生していることを確認します。 前の例の場合、 NumericUpDownRangeBase から派生しているため、ピアの基にする必要がある RangeBaseAutomationPeer クラスを使用できます。 コントロール自体の派生方法に最も近いピア クラスを並列に使用することで、基底ピア クラスによって既に実装されているため、 IRangeValueProvider 機能の少なくとも一部をオーバーライドしないようにすることができます。

基底 Control クラスには、対応するピア クラスがありません。 Control から派生するカスタム コントロールに対応するピア クラスが必要な場合は、FrameworkElementAutomationPeer からカスタム ピア クラスを派生させます。

ContentControlから直接派生した場合、そのクラスには、ピア クラスを参照する OnCreateAutomationPeer 実装がないため、既定のオートメーション ピア動作はありません。 そのため、 OnCreateAutomationPeer を実装して独自のピアを使用するか、 FrameworkElementAutomationPeer そのレベルのアクセシビリティ サポートがコントロールに適している場合はピアとして使用してください。

Note

通常、FrameworkElementAutomationPeer ではなく、AutomationPeer から派生させることはありません。 AutomationPeer から直接派生した場合はFrameworkElementAutomationPeerから取得される多くの基本的なアクセシビリティ サポートを複製する必要があります

カスタム ピア クラスの初期化

オートメーション ピアでは、基本初期化に所有者コントロールのインスタンスを使用するタイプ セーフなコンストラクターを定義する必要があります。 次の例では、実装は owner 値を RangeBaseAutomationPeer base に渡します。最終的には、実際に owner を使用して FrameworkElementAutomationPeer.Owner を設定するFrameworkElementAutomationPeerになります。

public NumericUpDownAutomationPeer(NumericUpDown owner): base(owner)
{}
Public Sub New(owner As NumericUpDown)
    MyBase.New(owner)
End Sub
// NumericUpDownAutomationPeer.idl
import "NumericUpDown.idl";
namespace MyNamespace
{
    runtimeclass NumericUpDownAutomationPeer : Windows.UI.Xaml.Automation.Peers.AutomationPeer
    {
        NumericUpDownAutomationPeer(NumericUpDown owner);
        Int32 MyProperty;
    }
}

// NumericUpDownAutomationPeer.h
...
struct NumericUpDownAutomationPeer : NumericUpDownAutomationPeerT<NumericUpDownAutomationPeer>
{
    ...
    NumericUpDownAutomationPeer(MyNamespace::NumericUpDown const& owner);
};
//.h
public ref class NumericUpDownAutomationPeer sealed :  Windows::UI::Xaml::Automation::Peers::RangeBaseAutomationPeer
//.cpp
public:    NumericUpDownAutomationPeer(NumericUpDown^ owner);

AutomationPeer のコア メソッド

UWP インフラストラクチャ上の理由から、オートメーション ピアのオーバーライド可能なメソッドは、UI オートメーション プロバイダーがUI オートメーション クライアントの転送ポイントとして使用するパブリック アクセス メソッドと、UWP クラスが動作に影響を与えるためにオーバーライドできる保護された "コア" カスタマイズ メソッドの 2 つのメソッドの一部です。 メソッドペアは、アクセス メソッドの呼び出しが常にプロバイダーの実装を持つ並列 "Core" メソッドを呼び出すように、またはフォールバックとして基底クラスから既定の実装を呼び出すように、既定で結合されます。

カスタム コントロールのピアを実装する場合は、カスタム コントロールに固有の動作を公開する基本オートメーション ピア クラスの "Core" メソッドのいずれかをオーバーライドします。 UI オートメーションコードは、ピア クラスのパブリック メソッドを呼び出すことによって、コントロールに関する情報を取得します。 コントロールに関する情報を提供するには、コントロールの実装と設計によって、基本オートメーション ピア クラスでサポートされているものとは異なるアクセシビリティ シナリオまたはその他のUI オートメーションシナリオを作成するときに、各メソッドを "Core" で終わる名前でオーバーライドします。

少なくとも、新しいピア クラスを定義するたびに、次の例に示すように、 GetClassNameCore メソッドを実装します。

protected override string GetClassNameCore()
{
    return "NumericUpDown";
}

Note

メソッド本体に直接格納するのではなく、文字列を定数として格納することもできますが、これはユーザーが行う必要があります。 GetClassNameCore の場合、この文字列をローカライズする必要はありません。 LocalizedControlType プロパティは、ClassNameではなく、UI オートメーション クライアントでローカライズされた文字列が必要な場合に常に使用されます。

GetAutomationControlType

一部の支援テクノロジでは、UI オートメーション ツリー内の項目の特性を報告するときにGetAutomationControlType UI オートメーション Name以外の追加情報として値を直接使用します。 コントロールが派生元のコントロールと大きく異なり、コントロールによって使用される基本ピア クラスによって報告されるコントロールの種類とは異なるコントロールの種類を報告する場合は、ピアを実装し、ピア実装で GetAutomationControlTypeCore をオーバーライドする必要があります。 これは、 ItemsControlContentControl などの一般化された基底クラスから派生する場合に特に重要です。この場合、基本ピアはコントロールの種類に関する正確な情報を提供しません。

GetAutomationControlTypeCore の実装では、AutomationControlType 値を返すことによってコントロールを記述します。 AutomationControlType.Customを返すことができますが、コントロールの主なシナリオを正確に記述している場合は、より具体的なコントロール型のいずれかを返す必要があります。 次に例を示します。

protected override AutomationControlType GetAutomationControlTypeCore()
{
    return AutomationControlType.Spinner;
}

Note

AutomationControlType.Custom を指定しない限り、クライアントに LocalizedControlType プロパティ値を提供するために、GetLocalizedControlTypeCore を実装する必要はありません。 UI オートメーション一般的なインフラストラクチャは、可能なすべてのに翻訳された文字列を提供しますAutomationControlTypeAutomationControlType.Custom以外の値

GetPattern と GetPatternCore

ピアの GetPatternCore の実装は、入力パラメーターで要求されたパターンをサポートするオブジェクトを返します。 具体的には、UI オートメーション クライアントは、プロバイダーの GetPattern メソッドに転送されるメソッドを呼び出し、要求されたパターンに名前を付けるPatternInterface 列挙値を指定します。 GetPatternCore のオーバーライドは、指定したパターンを実装するオブジェクトを返す必要があります。 ピアは、パターンをサポートしていることを報告するたびに対応するパターン インターフェイスを実装する必要があるため、そのオブジェクトはピア自体です。 ピアにパターンのカスタム実装がないが、ピアのベースでパターンが実装されていることがわかっている場合は、GetPatternCore から基本型の GetPatternCore の実装を呼び出すことができます。 ピアのGetPatternCoreは、ピアでパターンがサポートされていない場合null を返す必要があります。 ただし、実装から直接 null を返す代わりに、通常は基本実装の呼び出しに依存して、サポートされていないパターンに対して null を返します。

パターンがサポートされている場合、 GetPatternCore 実装は this または Me を返すことができます。 期待されるのは、UI オートメーション クライアントが null でない場合は常に、GetPattern 戻り値を要求されたパターン インターフェイスキャストすることです

ピア クラスが別のピアから継承され、必要なすべてのサポートとパターン レポートが基底クラスによって既に処理されている場合、 GetPatternCore の実装は必要ありません。 たとえば、 RangeBase から派生する範囲コントロールを実装していて、ピアが RangeBaseAutomationPeer から派生している場合、そのピアは PatternInterface.RangeValue に対して自身を返し、パターンをサポートする IRangeValueProvider インターフェイスの動作実装を持ちます。

リテラル コードではありませんが、この例では、 GetPatternCore RangeBaseAutomationPeer に既に存在する実装を近似しています。

protected override object GetPatternCore(PatternInterface patternInterface)
{
    if (patternInterface == PatternInterface.RangeValue)
    {
        return this;
    }
    return base.GetPatternCore(patternInterface);
}

基底ピア クラスから必要なすべてのサポートがないピアを実装している場合、またはピアがサポートできる基本継承パターンのセットを変更または追加する場合は、GetPatternCore をオーバーライドして、UI オートメーションクライアントでパターンを使用できるようにする必要があります。

UI オートメーション サポートの UWP 実装で使用できるプロバイダー パターンの一覧については、「Windows.UI.Xaml.Automation.Providerを参照してください。 このような各パターンには、PatternInterface 列挙体の対応する値があります。これは、クライアントが GetPattern 呼び出しでパターンUI オートメーション要求する方法です。

ピアは、複数のパターンをサポートしていることを報告できます。 その場合、オーバーライドには、サポートされている各 PatternInterface 値の戻りパス ロジックを含め、一致する各ケースでピアを返す必要があります。 呼び出し元が一度に要求するインターフェイスは 1 つだけであり、必要なインターフェイスにキャストするのは呼び出し元が行う必要があります。

カスタム ピアの GetPatternCore オーバーライドの例を次に示します。 IRangeValueProviderIToggleProvider の 2 つのパターンのサポートを報告します。 ここでのコントロールは、全画面表示 (トグル モード) として表示でき、ユーザーが位置 (範囲コントロール) を選択できる進行状況バーを備えるメディア表示コントロールです。 このコードは、 XAML アクセシビリティ サンプルから取得したものです。

protected override object GetPatternCore(PatternInterface patternInterface)
{
    if (patternInterface == PatternInterface.RangeValue)
    {
        return this;
    }
    else if (patternInterface == PatternInterface.Toggle)
    {
        return this;
    }
    return null;
}

サブ要素からの転送パターン

GetPatternCore メソッドの実装では、サブ要素または部分をホストのパターン プロバイダーとして指定することもできます。 この例では、 ItemsControl が内部の ScrollViewer コントロールのピアにスクロール パターン処理を転送する方法を模倣します。 パターン処理のサブ要素を指定するために、このコードはサブ要素オブジェクトを取得し、 FrameworkElementAutomationPeer.CreatePeerForElement メソッドを使用してサブ要素のピアを作成し、新しいピアを返します。

protected override object GetPatternCore(PatternInterface patternInterface)
{
    if (patternInterface == PatternInterface.Scroll)
    {
        ItemsControl owner = (ItemsControl) base.Owner;
        UIElement itemsHost = owner.ItemsHost;
        ScrollViewer element = null;
        while (itemsHost != owner)
        {
            itemsHost = VisualTreeHelper.GetParent(itemsHost) as UIElement;
            element = itemsHost as ScrollViewer;
            if (element != null)
            {
                break;
            }
        }
        if (element != null)
        {
            AutomationPeer peer = FrameworkElementAutomationPeer.CreatePeerForElement(element);
            if ((peer != null) && (peer is IScrollProvider))
            {
                return (IScrollProvider) peer;
            }
        }
    }
    return base.GetPatternCore(patternInterface);
}

その他のコア メソッド

コントロールでは、主要なシナリオで同等のキーボードをサポートすることが必要な場合があります。これが必要になる理由の詳細については、「 Keyboard アクセシビリティを参照してください。 キーサポートの実装は、コントロールのロジックの一部であるため、ピア コードではなく、必ずしもコントロール コードの一部ですが、ピア クラスは、GetAcceleratorKeyCore および GetAccessKeyCore メソッドをオーバーライドして、キーが使用されているUI オートメーションクライアントに報告する必要があります。 キー情報を報告する文字列はローカライズする必要があるため、ハードコーディングされた文字列ではなくリソースから取得する必要があることを検討してください。

コレクションをサポートするクラスのピアを提供する場合は、関数型クラスと、その種類のコレクションが既にサポートされているピア クラスの両方から派生することをお勧めします。 これを行えない場合、子コレクションを維持するコントロールのピアは、コレクション関連のピア メソッド GetChildrenCore をオーバーライドして、親子関係をUI オートメーション ツリーに適切に報告する必要があります。

IsContentElementCore および IsControlElementCore メソッドを実装して、コントロールにデータ コンテンツが含まれているか、ユーザー インターフェイス (またはその両方) で対話型の役割を果たすかを示します。 既定では、どちらのメソッドも true を返します。 これらの設定により、スクリーン リーダーなどの支援技術の使いやすさが向上します。これらの方法を使用してオートメーション ツリーをフィルター処理する場合があります。 GetPatternCore メソッドがパターン処理をサブ要素ピアに転送する場合、サブ要素ピアの IsControlElementCore メソッドは false を返して、サブ要素ピアをオートメーション ツリーから非表示にすることができます。

一部のコントロールでは、ラベル付けシナリオがサポートされている場合があります。テキスト ラベル パーツがテキスト以外の部分の情報を提供する場合や、コントロールが UI 内の別のコントロールとの既知のラベル付け関係にある場合があります。 有用なクラスベースの動作を提供できる場合は、 GetLabeledByCore をオーバーライドしてこの動作を提供できます。

GetBoundingRectangleCore および GetClickablePointCore は、主に自動テスト シナリオに使用されます。 コントロールの自動テストをサポートする場合は、これらのメソッドをオーバーライドできます。 これは、ユーザーが座標空間内をクリックする場所が範囲に対して異なる効果を持つので、単一のポイントだけを提案できない範囲型コントロールに必要な場合があります。 たとえば、既定の ScrollBar オートメーション ピアは、 GetClickablePointCore をオーバーライドして、"not a number" Point 値を返します。

GetLiveSettingCore は、UI オートメーションの LiveSetting 値のコントロールの既定値に影響します。 コントロールが AutomationLiveSetting.Off 以外の値を返す場合は、これをオーバーライドできます。 LiveSettingが表す内容の詳細については、「AutomationProperties.LiveSettingを参照してください。

コントロールにAutomationOrientationにマップできる設定可能な方向プロパティがある場合はgetOrientationCoreオーバーライドできます。 ScrollBarAutomationPeer および SliderAutomationPeer クラスでこれを行います。

FrameworkElementAutomationPeer での基本実装

FrameworkElementAutomationPeer の基本実装では、フレームワーク レベルで定義されているさまざまなレイアウトおよび動作プロパティから解釈できるいくつかのUI オートメーション情報が提供されます。

  • GetBoundingRectangleCore: 既知のレイアウト特性に基づいて Rect 構造体を返します。 IsOffscreentrue の場合は、0 値の Rect を返します
  • GetClickablePointCore: 0 以外の BoundingRectangle がある限り、既知のレイアウト特性に基づいて Point 構造体を返します。
  • GetNameCore: ここで要約できるよりも広範な動作です。 GetNameCoreを参照してください。 基本的には、 ContentControl またはコンテンツを持つ関連クラスの既知のコンテンツに対して文字列変換を試みます。 また、 LabeledBy の値がある場合は、その項目の Name 値が Name として使用されます。
  • HasKeyboardFocusCore: 所有者の FocusState プロパティと IsEnabled プロパティに基づいて評価されます。 コントロールではない要素は常に falseを返します。
  • IsEnabledCore: 所有者の IsEnabled プロパティが Control の場合に基づいて評価されます。 コントロールではない要素は常に trueを返します。 これは、所有者が従来の相互作用の意味で有効になっていることを意味するものではありません。これは、所有者が IsEnabled プロパティを持っていないにもかかわらず、ピアが有効になっていることを意味します。
  • IsKeyboardFocusableCore: 所有者が Control の場合は true を返します。それ以外の場合はfalse
  • IsOffscreenCore: 所有者要素またはその親の Collapsed非表示は、IsOffscreentrue 値に相当します。 例外: Popup オブジェクトは、その所有者の親ではない場合でも表示できます。
  • SetFocusCore: Focus を呼び出します。
  • GetParent: 所有者から FrameworkElement.Parent を呼び出し、適切なピアを検索します。 これは "Core" メソッドを使用したオーバーライド ペアではないので、この動作を変更することはできません。

Note

既定の UWP ピアは、UWP を実装する内部ネイティブ コードを使用して動作を実装します。実際の UWP コードを使用するとは限りません。 共通言語ランタイム (CLR) リフレクションまたはその他の手法を使用して、実装のコードまたはロジックを確認することはできません。 また、基本ピア動作のサブクラス固有のオーバーライドに対する個別の参照ページも表示されません。 たとえば、TextBoxAutomationPeerGetNameCoreの動作が追加される可能性があります。この動作は、AutomationPeer.GetNameCore リファレンス ページでは説明しません。また、TextBoxAutomationPeer.GetNameCore の参照ページはありません。 TextBoxAutomationPeer.GetNameCore 参照ページもありません。 代わりに、最も直接的なピア クラスのリファレンス トピックを読み、「解説」セクションで実装ノートを探します。

ピアと AutomationProperties

オートメーション ピアは、コントロールのアクセシビリティ関連の情報に適切な既定値を指定する必要があります。 コントロールを使用するアプリ コードでは、コントロール インスタンスに添付プロパティ値 automationProperties を含めることで、その動作の一部をオーバーライドできることに注意してください。 呼び出し元は、既定のコントロールまたはカスタム コントロールに対してこれを行うことができます。 たとえば、次の XAML は、カスタマイズされた 2 つのUI オートメーション プロパティを持つボタンを作成します。<Button AutomationProperties.Name="Special" AutomationProperties.HelpText="This is a special button."/>

添付プロパティ AutomationProperties の詳細については、「 Basic アクセシビリティ情報を参照してください。

AutomationPeer メソッドの一部は、UI オートメーション プロバイダーが情報を報告する方法の一般的なコントラクトのために存在しますが、これらのメソッドは通常、コントロール ピアに実装されません。 これは、特定の UI でコントロールを使用するアプリ コードに適用される AutomationProperties 値によって情報が提供されることが想定されているためです。 たとえば、ほとんどのアプリでは、 AutomationProperties.LabeledBy 値を適用することで、UI 内の 2 つの異なるコントロール間のラベル付け関係を定義します。 ただし、 LabeledByCore は、ヘッダー パーツを使用してデータ フィールド パーツにラベルを付ける、項目にコンテナーをラベル付けする、または同様のシナリオなど、コントロール内のデータまたは項目のリレーションシップを表す特定のピアに実装されます。

パターンの実装

展開折りたたみのコントロール パターン インターフェイスを実装して、展開/折りたたみ動作を実装するコントロールのピアを記述する方法を見てみましょう。 ピアは、 GetPatternPatternInterface.ExpandCollapse の値で呼び出されるたびに、自身を返すことによって、展開/折りたたみ動作のアクセシビリティを有効にする必要があります。 その後、ピアはそのパターンのプロバイダー インターフェイス (IExpandCollapseProvider) を継承し、そのプロバイダー インターフェイスの各メンバーの実装を提供する必要があります。 この場合、インターフェイスにはオーバーライドする 3 つのメンバーがあります。 ExpandCollapseExpandCollapseState

クラス自体の API 設計でアクセシビリティを事前に計画しておくと便利です。 UI で作業しているユーザーとの一般的なやり取りの結果として、またはオートメーション プロバイダー パターンを介して要求される可能性のある動作がある場合は、UI 応答またはオートメーション パターンを呼び出すことができる単一のメソッドを指定します。 たとえば、コントロールに、コントロールを展開または折りたたむことができるワイヤード (有線) イベント ハンドラーを持ち、それらのアクションに対応するキーボードを持つボタン パーツがある場合、これらのイベント ハンドラーは、ピアの Expand または Collapse 実装の本体内から呼び出すのと同じメソッド IExpandCollapseProvider を呼び出します。 一般的なロジック メソッドを使用すると、動作の呼び出し方法に関係なく、コントロールの表示状態が一様な方法で表示されるように、コントロールの表示状態を確実に更新するのに役立ちます。

一般的な実装では、プロバイダー API は、実行時にコントロール インスタンスにアクセスするために最初に Owner を呼び出します。 その後、そのオブジェクトに対して必要な動作メソッドを呼び出すことができます。

public class IndexCardAutomationPeer : FrameworkElementAutomationPeer, IExpandCollapseProvider {
    private IndexCard ownerIndexCard;
    public IndexCardAutomationPeer(IndexCard owner) : base(owner)
    {
         ownerIndexCard = owner;
    }
}

別の実装は、コントロール自体がそのピアを参照できることです。 これは、 RaiseAutomationEvent メソッドがピア メソッドであるため、コントロールからオートメーション イベントを発生させる場合に一般的なパターンです。

UI オートメーション イベント

UI オートメーションのイベントは、次のカテゴリに分類されます。

Event 説明
プロパティの変更 UI オートメーション要素またはコントロール パターンのプロパティが変更されたときに発生します。 たとえば、クライアントがアプリのチェック ボックス コントロールを監視する必要がある場合、 ToggleState プロパティのプロパティ変更イベントをリッスンするように登録できます。 チェック ボックス コントロールがオンまたはオフの場合、プロバイダーはイベントを発生させ、クライアントは必要に応じて動作できます。
要素のアクション UI の変更がユーザーまたはプログラムによるアクティビティの結果として発生すると発生します。たとえば、 Invoke パターンを使用してボタンがクリックまたは呼び出されたときなどです。
構造の変更 UI オートメーション ツリーの構造が変更されたときに発生します。 構造は、新しい UI 項目が表示された場合、非表示になった場合、またはデスクトップから削除された場合に変更されます。
グローバルな変更 フォーカスが要素間で移動したときや子ウィンドウが閉じた場合など、クライアントに対してグローバルに関心のあるアクションが発生したときに発生します。 イベントによっては、必ずしも UI の状態が変更されたことを意味しません。 たとえば、ユーザーがテキスト入力フィールドにタブを移動し、ボタンをクリックしてフィールドを更新すると、ユーザーが実際にテキストを変更しなかった場合でも、 TextChanged イベントが発生します。 イベントを処理する際、クライアント アプリケーションがアクションを起こす前に、実際に変更が行われたかどうかのチェックが必要となる場合があります。

AutomationEvents 識別子

UI オートメーションイベントはによって識別されますAutomationEvents 値。 列挙体の値は、イベントの種類を一意に識別します。

イベントの発生

UI オートメーションクライアントはオートメーション イベントをサブスクライブできます。 オートメーション ピア モデルでは、カスタム コントロールのピアは、 RaiseAutomationEvent メソッドを呼び出すことによって、アクセシビリティに関連するコントロール状態の変更を報告する必要があります。 同様に、キー UI オートメーションプロパティ値が変更されると、カスタム コントロール ピアは RaisePropertyChangedEvent メソッドを呼び出す必要があります。

次のコード例では、コントロール定義コード内からピア オブジェクトを取得し、そのピアからイベントを発生させるメソッドを呼び出す方法を示します。 最適化として、このコードは、このイベントの種類のリスナーがあるかどうかを判断します。 イベントを発生させ、リスナーがある場合にのみピア オブジェクトを作成すると、不要なオーバーヘッドが回避され、コントロールの応答性が維持されます。

if (AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged))
{
    NumericUpDownAutomationPeer peer =
        FrameworkElementAutomationPeer.FromElement(nudCtrl) as NumericUpDownAutomationPeer;
    if (peer != null)
    {
        peer.RaisePropertyChangedEvent(
            RangeValuePatternIdentifiers.ValueProperty,
            (double)oldValue,
            (double)newValue);
    }
}

ピア ナビゲーション

オートメーション ピアを見つけた後、UI オートメーション クライアントは、ピア オブジェクトの GetChildren メソッドと GetParent メソッドを呼び出すことによって、アプリのピア構造をナビゲートできます。 コントロール内の UI 要素間のナビゲーションは、ピアの GetChildrenCore メソッドの実装によってサポートされます。 UI オートメーション システムは、このメソッドを呼び出して、コントロールに含まれるサブ要素のツリー (リスト ボックス内のリスト アイテムなど) を構築します。 FrameworkElementAutomationPeer の既定の GetChildrenCore メソッドはオートメーション ピアのツリーを構築するために要素のビジュアル ツリーを走査します。 カスタム コントロールは、このメソッドをオーバーライドして、子要素の異なる表現をオートメーション クライアントに公開し、情報を伝達したり、ユーザーの操作を許可したりする要素のオートメーション ピアを返すことができます。

テキスト パターンに対するネイティブオートメーションのサポート

既定の UWP アプリオートメーション ピアの一部では、テキスト パターン (PatternInterface.Text) のコントロール パターンのサポートが提供されています。 ただし、ネイティブ メソッドを使用してこのサポートを提供します。関係するピアは、(マネージド) 継承の ITextProvider インターフェイスをメモしません。 それでも、管理対象または非管理対象のUI オートメーションクライアントがピアにパターンを照会した場合、テキスト パターンのサポートが報告され、クライアント API が呼び出されたときにパターンの一部の動作が提供されます。

UWP アプリのテキスト コントロールの 1 つから派生し、テキスト関連のピアの 1 つから派生するカスタム ピアを作成する場合は、ピアの「解説」セクションを参照して、パターンのネイティブ レベルのサポートの詳細を確認してください。 マネージド プロバイダー インターフェイスの実装から基本実装を呼び出す場合、カスタム ピアのネイティブ基本動作にアクセスできますが、ピアとその所有者コントロールの両方のネイティブ インターフェイスが公開されていないため、基本実装の動作を変更することは困難です。 通常、基本実装をそのまま使用するか (呼び出しベースのみ)、機能を独自のマネージド コードに完全に置き換え、基本実装を呼び出さないでください。 後者は高度なシナリオであり、そのフレームワークを使用する際のアクセシビリティ要件をサポートするために、コントロールで使用されているテキスト サービス フレームワークをよく理解している必要があります。

AutomationProperties.AccessibilityView

カスタム ピアを提供するだけでなく、XAML で AutomationProperties.AccessibilityView を設定することで、任意のコントロール インスタンスのツリー ビュー表現を調整することもできます。 これはピア クラスの一部として実装されていませんが、ここでは、カスタム コントロールまたはカスタマイズするテンプレートに対する全体的なアクセシビリティ サポートに対してドイツ語で説明します。

AutomationProperties.AccessibilityView を使用する主なシナリオは、テンプレート内の特定のコントロールをUI オートメーション ビューから意図的に省略することです。これは、コントロール全体のアクセシビリティ ビューには意味がないためです。 これを防ぐには、 AutomationProperties.AccessibilityView を "Raw" に設定します。

オートメーション ピアからの例外のスロー

オートメーション ピア サポート用に実装している API は、例外をスローすることが許可されています。 リッスンしているUI オートメーションクライアントは、ほとんどの例外がスローされた後も続行するのに十分な堅牢性が期待されます。 リスナーが独自のアプリ以外のアプリを含むオールアップオートメーションツリーを見ている可能性は高く、クライアントが API を呼び出したときにツリーの 1 つの領域がピアベースの例外をスローしたからといって、クライアント全体をダウンさせるのは許容できないクライアント設計です。

ピアに渡されるパラメーターの場合、入力を検証できます。たとえば、ArgumentNullException をスローnullが実装に対して有効な値でない場合にスローします。 ただし、ピアによって後続の操作が実行される場合は、ピアとホスティング コントロールの相互作用に非同期文字があることに注意してください。 ピアが必ずしもコントロール内の UI スレッドをブロックするとは限りません (おそらくブロックしないでください)。 そのため、ピアが作成されたとき、またはオートメーション ピア メソッドが最初に呼び出されたとき、その間にコントロールの状態が変化したときに、オブジェクトが使用可能であったり、特定のプロパティを持っていたりする状況が発生する可能性があります。 このような場合、プロバイダーがスローできる専用の例外が 2 つあります。

  • API が渡された元の情報に基づいてピアの所有者または関連するピア要素にアクセスできない場合はElementNotAvailableException をスローします。 たとえば、メソッドを実行しようとしているが、その後、所有者が UI から削除されているピア (閉じられたモーダル ダイアログなど) があるとします。 .NET 以外のクライアントでは、これは UIA_E_ELEMENTNOTAVAILABLE にマップされます。
  • 所有者がまだ存在するが、その所有者がIsEnabled=false などのモードにある場合はElementNotEnabledException をスローします。これにより、ピアが実行しようとしているプログラムによる特定の変更の一部がブロックされます。 .NET 以外のクライアントでは、これは UIA_E_ELEMENTNOTENABLED にマップされます。

それ以外に、ピアサポートからスローされる例外に関しては、ピアは比較的保守的である必要があります。 ほとんどのクライアントでは、ピアからの例外を処理できず、ユーザーがクライアントと対話するときに実行可能な選択肢に変換できます。 そのため、ピアの実装内で再スローすることなく、操作不要で例外をキャッチする方が、ピアが実行しようとするたびに例外をスローするよりも優れた戦略です。 また、ほとんどのUI オートメーションクライアントがマネージド コードで記述されていないことも考慮してください。 ほとんどは COM で記述されているため、最終的にピアにアクセスする UI オートメーション クライアント メソッドを呼び出すときは、HRESULTS_OK かどうかをチェックするだけになります。