自訂自動化對等
說明 Microsoft UI 自動化中的自動化對等概念,以及如何為自訂 UI 類別提供自動化支援。
UI 自動化提供了一個架構,可讓自動化用戶端用來檢查或操作各種 UI 平台和架構的使用者介面。 如果您正在撰寫 Windows 應用程式,則您的 UI 所使用的類別已經提供 UI 自動化支援。 您可以從現有的非密封類別衍生,以定義新的 UI 控制項或支援類別。 在此過程中,您的類別可能會新增應該支援協助工具、但預設的 UI 自動化支援並未涵蓋的行為。 在此情況下,您應該擴充現有的 UI 自動化支援,方法是從基底實作所使用的 AutomationPeer 類別衍生、為對等實作新增任何必要的支援,並通知 Windows 應用程式控制基礎結構應建立新的對等。
UI 自動化不僅支援協助工具應用程式和輔助技術 (例如螢幕助讀程式),還支援品質保證 (測試) 程式碼。 無論是在哪一種情況下,UI 自動化用戶端都可以檢查使用者介面元素,並透過應用程式外部的其他程式碼,模擬使用者與應用程式的互動。 如需跨所有平台的 UI 自動化及其更廣泛含義的相關資訊,請參閱 UI 自動化概觀。
UI 自動化架構有兩種不同的適用對象。
- UI 自動化用戶端會呼叫 UI 自動化 API,以了解目前向使用者顯示的所有 UI。 例如,螢幕助讀程式等輔助技術可擔任 UI 自動化用戶端。 UI 會顯示為相關自動化元素的樹狀結構。 UI 自動化用戶端可能一次只對一個應用程式感興趣,或對整個樹狀結構感興趣。 UI 自動化用戶端可以使用 UI 自動化 API 來巡覽樹狀結構,並讀取或變更自動化元素中的資訊。
- UI 自動化提供者會藉由實作 API 來公開其作為應用程式一部分引進 UI 中的元素,藉此將資訊提供給 UI 自動化樹狀結構。 當您建立新控制項時,您現在應該擔任 UI 自動化提供者情境的參與者。 身為提供者,您應確保所有 UI 自動化用戶端都可以使用 UI 自動化架構與您的控制項互動,以同時滿足協助工具和測試需求。
UI 自動化架構中通常會有平行 API 存在:其中一個 API 供 UI 自動化用戶端使用,另一個名稱類似的 API 則供 UI 自動化提供者使用。 本主題的大部分內容涵蓋適用於 UI 自動化提供者的 API,特別是該 UI 架構中為提供者提供擴充性的類別和介面。 我們偶爾會提到 UI 自動化用戶端使用的 UI 自動化 API,藉此提供一些觀點,或提供用來確立用戶端和提供者 API 關聯的查閱資料表。 如需有關用戶端觀點的詳細資訊,請參閱 UI 自動化用戶端程式設計人員指南。
注意
UI 自動化用戶端通常不會使用 Managed 程式碼,而且通常不會實作為 UWP 應用程式 (通常是傳統型應用程式)。 UI 自動化是基於標準,而不是基於特定的實作或架構。 許多現有的 UI 自動化用戶端,包括輔助技術產品 (例如螢幕助讀程式),都是使用元件物件模型 (COM) 介面,與 UI 自動化、系統以及在子視窗中執行的應用程式進行互動。 如需有關 COM 介面、以及如何使用 COM 編寫 UI 自動化用戶端的詳細資訊,請參閱 UI 自動化基礎觀念。
判斷 UI 自動化對自訂 UI 類別的現有支援狀態
在嘗試為自訂控制項實作自動化對等之前,您應該測試基底類別及其自動化對等是否已提供所需的協助工具或自動化支援。 在許多情況下,搭配運用 FrameworkElementAutomationPeer 實作、特定對等及其實作的模式,已能提供基本但令人滿意的協助工具體驗。 這點是否為真,取決於您對向控制項公開的物件模型所進行的變更次數,與您對其基底類別進行的變更次數兩者之間的差異。 此外,這也取決於您新增的基底類別功能,是與範本協定中的新 UI 元素相關、還是與控制項的視覺外觀相關。 在某些情況下,您的變更可能會產生新的使用者體驗,並需要額外的協助工具支援。
即使已使用現有的基底對等類別提供了基本的協助工具支援,根據最佳做法,仍建立您定義對等,以便向 UI 自動化回報精確的 ClassName 資訊,以實現自動化測試場景。 如果您正在編寫供第三方使用的控制項,則這項考量格外重要。
自動化對等類別
UWP 是以舊版 Managed 程式碼 UI 架構所使用的現有 UI 自動化技術和慣例為基礎,例如 Windows Forms、Windows Presentation Foundation (WPF) 和 Microsoft Silverlight。 許多控制項類別及其功能和用途,皆起源於先前的 UI 架構。
依照慣例,對等類別名稱會以控制項類別名稱開始,並以 "AutomationPeer" 結束。 例如,ButtonAutomationPeer 是 Button 控制項類別的對等類別。
注意
在本主題之下,我們將與協助工具相關的屬性,視為對於實作控制項對等來說更加重要的屬性。 但針對更廣義的 UI 自動化支援概念,您應該依照 UI 自動化提供者程式設計人員指南和 UI 自動化基礎觀念中所述的建議來實作對等。 這些主題並未涵蓋用於在 UI 自動化的 UWP 架構中提供資訊的特定 AutomationPeer API,但會針對用來識別您的類別、或提供其他資訊或互動的屬性進行說明。
對等、模式和控制項類型
控制項模式是一種介面實作,旨在向 UI 自動化用戶端公開控制項功能的特定面向。 UI 自動化用戶端會使用透過控制項模式公開的屬性和方法,來擷取控制項功能的相關資訊,或在執行階段操縱控制項的行為。
控制項模式提供一種方式,分類及公開與控制項類型或控制項外觀無關的控制項功能。 例如,呈現表格式介面的控制項會使用 Grid 控制項模式,公開資料表中的列數和欄數,讓 UI 自動化用戶端能夠從資料表中擷取項目。 其他例子還包括,UI 自動化用戶端可以使用 Invoke 控制項模式,用於可以叫用的控制項 (例如按鈕);也可以使用 Scroll 控制項模式,用於具有捲軸的控制項 (例如清單方塊、清單檢視或下拉式方塊)。 每個控制項模式都代表個別的功能類型,所以可以結合起來,用以描述特定控制項所支援的完整功能集。
控制項模式與 UI 相關聯,如同介面與 COM 物件相關聯。 在 COM 中,您可以查詢物件以詢問支援哪個介面,然後使用這些介面來存取功能。 在 UI 自動化中,UI 自動化用戶端可以查詢 UI 自動化元素,以找出它支援哪些控制項模式,然後透過受支援的控制項模式所公開的屬性、方法、事件和結構,與該元素及其對等控制項進行互動。
自動化對等的主要用途之一,是向 UI 自動化用戶端回報 UI 元素可透過其對等支援的控制項模式。 為此,UI 自動化提供者實作了新的對等,藉由覆寫 GetPatternCore 方法來變更 GetPattern 方法的行為。 UI 自動化用戶端會發出叫用,要求 UI 自動化提供者對應叫用 GetPattern。 UI 自動化用戶端會查詢它們想要互動的每個特定模式。 如果對等支援該模式,就會傳回自身的物件參考;否則會傳回 null。 如果傳回值不是 null,則 UI 自動化用戶端預期可以擔任用戶端叫用模式介面的 API,以便與該控制項模式互動。
控制項類型是一種廣泛定義對等所代表之控制項功能的方法。 這與控制項模式是兩個不同的概念;雖然控制項模式會通知 UI 自動化,它可以透過特定介面取得哪些資訊或執行哪些操作,但控制項類型存在於更高一個層級。 每個控制項類型都有關於這些 UI 自動化面向的指引:
- UI 自動化控制項模式:控制項類型可能支援多個模式,每個模式都代表不同的資訊或互動分類。 每個控制項類型都有一組該控制項必須支援的控制項模式、一組可選的控制項模式,以及一組該控制項不得支援的控制項模式。
- UI 自動化屬性值:每個控制項類型都有一組該控制項必須支援的屬性。 這些是一般屬性 (如 UI 自動化屬性概觀中所述),而不是模式專用的屬性。
- UI 自動化事件:每種控制項類型都有一組該控制項必須支援的事件。 同樣,這些屬性都是一般屬性,而不是模式專用屬性,如 UI 自動化事件概觀中所述。
- UI 自動化樹狀結構:每種控制項類型都會定義控制項在 UI 自動化樹狀結構中的顯示方式。
無論架構的自動化對等以何種方式實作,UI 自動化用戶端功能都不會繫結至 UWP;事實上,現有的 UI 自動化客戶端 (例如輔助技術) 可能會使用其他程式設計模型,例如 COM。 在 COM 中,用戶端可以透過 QueryInterface,查詢用來實作所要求模式的 COM 控制項模式介面,或是用於屬性、事件或樹狀結構檢查的一般 UI 自動化架構。 針對這些模式,UI 自動化架構會將該介面程式碼橋接至針對應用程式的 UI 自動化供應商與相關對等執行的 UWP 程式碼中。
當您使用 C# 或 Microsoft Visual Basic 為 UWP 應用程式等 Managed 程式碼架構實作控制項模式時,您可以使用 .NET Framework 介面來表示這些模式,而不是使用 COM 介面表示法。 例如,Invoke 模式的 Microsoft .NET 提供者實作的 UI 自動化模式介面是 IInvokeProvider。
如需有關控制項模式、提供者介面及其用途的清單,請參閱控制項模式和介面。 如需控制項類型的清單,請參閱 UI 自動化控制項類型概觀。
控制項模式實作指引
控制項模式及其用途是更廣泛 UI 自動化架構定義的一部分,因此不僅適用於 UWP 應用程式的協助工具支援。 實作控制項模式時,您應確保您的實作方式與這些文件以及 UI 自動化規格中的指引相符。 如需相關指引,您通常可以參考 Microsoft 文件,而無需參考規格。 實作 UI 自動化控制項模式中記錄了每種模式的指引。 您會注意到,此區域下的每個主題都有一個「實作方針和慣例」部分,以及一個「必要成員」部分。 相關指引通常會提到提供者控制項模式介面參考資料中相關控制項模式介面的特定 API。 這些介面是原生/COM 介面 (且其 API 會使用 COM 樣式語法)。 然而,您這些介面中看到的所有內容,在 Windows.UI.Xaml.Automation.Provider 命名空間中都有對應的內容。
如果您使用預設的自動化對等、並擴充其行為,則這些對等已按照 UI 自動化指導方針編寫。 如果它們支援控制項模式,您可以依賴該模式支援,遵循實作 UI 自動化控制項模式中的指引。 如果某個控制項對等回報,它代表 UI 自動化所定義的控制項類型,則該對等已遵循支援 UI 自動化控制項類型中的指引。
不過,您可能需要遵循有關控制項模式或控制類型的額外指引,才能在對等實作中遵循 UI 自動化建議。 如果您正在實作尚未成為 UWP 控制項預設實作的模式或控制項類型支援,那就更是如此了。 例如,註釋模式不會在任何預設 XAML 控制項中實作。 但您可能有一個廣泛使用註釋的應用程式,因此您想要呈現該功能可供存取。 在此案例中,您的對等應實作 IAnnotationProvider,且應將自身回報為具有適當屬性的 Document 控制項類型,以指出您的文件支援註釋。
建議您以實作 UI 自動化控制項模式中的模式指引、或是支援 UI 自動化控制項類型中的控制項類型指引,做為導引和一般指引。 您甚至可以嘗試關注一些 API 連結,以取得有關 API 用途的說明和備註。 但針對 UWP 應用程式之程式設計所需的語法細節,請在 Windows.UI.Xaml.Automation.Provider 命名空間中尋找等效的 API,並透過這些參考頁面取得更多資訊。
內建自動化對等類別
一般來說,如果元素接受來自使用者的 UI 活動、或是包含輔助技術使用者所需的資訊 (代表該元素是應用程式的互動式或重要 UI),就需要實作自動化對等類別。 並非所有 UWP 視覺元素都有自動化對等。 實作自動化對等的類別例子包括 Button 和 TextBox。 未實作自動化對等的類別例子包括 Border 以及基於 Panel 的類別,例如 Grid 和 Canvas。 Panel 沒有對等,因為它提供的版面配置行為僅限於視覺效果。 使用者無法使用任何協助工具相關功能,與 Panel 進行互動。 無論 Panel 包含什麼子元素,都會作為 UI 自動化樹狀結構中具有對等或元素表示法的下一個可用父元素的子元素,向 UI 自動化樹狀結構回報。
UI 自動化和 UWP 程序界限
存取 UWP 應用程式的 UI 自動化用戶端程式碼,通常會在程序外執行。 UI 自動化架構基礎結構可讓資訊跨越程序界限。 UI 自動化基礎觀念會更詳細地說明這個概念。
OnCreateAutomationPeer
衍生自 UIElement 的所有類別,都包含受保護的虛擬方法 OnCreateAutomationPeer。 自動化對等的物件初始化序列會呼叫 OnCreateAutomationPeer 來取得每個控制項的自動化對等物件,進而建構一個 UI 自動化樹狀結構供執行階段使用。 UI 自動化程式碼可以使用對等來取得控制項特性和功能的相關資訊,並透過控制項模式模擬互動式使用。 支援自動化的自訂控制項必須覆寫 OnCreateAutomationPeer,並傳回衍生自 AutomationPeer 之類別的執行個體。 例如,如果自訂控制項衍生自 ButtonBase 類別,則 OnCreateAutomationPeer 傳回的物件應衍生自 ButtonBaseAutomationPeer。
如果您正在編寫自訂控制項類別,並想要同時提供新的自動化對等,則您應覆寫自訂控制項的 OnCreateAutomationPeer 方法,讓它傳回對等的新執行個體。 您的對等類別必須直接或間接衍生自 AutomationPeer。
例如,以下程式碼會宣告自訂控制項NumericUpDown
應將對等用於NumericUpDownPeer
UI 自動化目的。
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);
}
};
注意
OnCreateAutomationPeer 實作應僅初始化自訂自動化對等的新執行個體、傳遞呼叫控制項作為擁有者,並傳回該執行個體。 請勿嘗試使用此方法中的其他邏輯。 更明確地說,任何可能導致同一呼叫內 AutomationPeer 損毀的邏輯,都可能導致非預期的執行階段行為。
在 OnCreateAutomationPeer 的典型實作中,擁有者會被指定為 this 或 Me,因為方法覆寫與 控制項類別定義的其餘部分位於相同的範圍內。
實際的對等類別定義可以在與控制項相同的程式碼檔案中完成,也可以在單獨的程式碼檔案中完成。 對等定義全都位於 Windows.UI.Xaml.Automation.Peers 命名空間中,該命名空間與它們為其提供對等之控制項所在的命名空間是分開的。 您也可以選擇在單獨的命名空間中宣告對等,只要引用 OnCreateAutomationPeer 方法呼叫所需的命名空間即可。
選擇正確的對等基底類別
請確保您的 AutomationPeer 衍生自一個基底類別,該基底類別必須最符合做為衍生來源之控制類別的現有對等邏輯。 在前一個範例中,因為 NumericUpDown
衍生自 RangeBase,因此有一個 RangeBaseAutomationPeer 類別可供您做為對等基礎。 藉由平行於您衍生控制項本身的方式使用最接近的相符對等類別,您至少可以避免覆寫某些 IRangeValueProvider 功能,因為基底對等類別已經實作了這些功能。
Control 基底類別沒有對應的對等類別。 如果您需要一個與從 Control 衍生的自訂控制項相對應的對等類別,請從 FrameworkElementAutomationPeer 衍生該自訂對等類別。
如果您直接從 ContentControl 衍生,則該類別沒有預設的自動化對等行為,因為不存在引用對等類別的 OnCreateAutomationPeer 實作。 因此,請務必實作 OnCreateAutomationPeer 以使用您自己的對等,或使用 FrameworkElementAutomationPeer 做為對等 (如果該層級的協助工具支援對您的控制項來說已經足夠)。
注意
從 AutomationPeer 而非 FrameworkElementAutomationPeer 衍生的情況並不常見。 如果您確實直接從 AutomationPeer 衍生,您將需要複製許多基本的協助工具支援,因為這些支援本應來自 FrameworkElementAutomationPeer。
自訂對等類別的初始化
自動化對等應該定義一個型別安全的建構函式,該函式使用擁有者控制項的執行個體進行基底初始化。 在下一個範例中,實作會將擁有者值傳遞到 RangeBaseAutomationPeer 基底,最終將由實際使用擁有者的 FrameworkElementAutomationPeer 來設定 FrameworkElementAutomationPeer.Owner。
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 類別可覆寫以影響行為的受保護「核心」自訂方法。 這對方法預設會以這種方式連接在一起:對存取方法的呼叫一律叫用具有提供者實作的平行「Core」方法,或者作為後援,從基底類別叫用預設實作。
為自訂控制項實施對等時,如果想要公開該自訂控制項特有的行為,請覆寫基底自動化對等類別中對應的任何的「核心」方法。 UI 自動化程式碼會呼叫對等類別的公用方法,來取得控制項的相關資訊。 為了提供控制項的相關資訊,請在控制項實作及設計所建立的協助工具場景或其他 UI 自動化場景不同於基底自動化對等類別所支援的場景時,覆寫每個名稱以「Core」結尾的方法。
至少,每當定義新的對等類別時,請實作 GetClassNameCore 方法,如下一個範例所示。
protected override string GetClassNameCore()
{
return "NumericUpDown";
}
注意
您可能想要將字串儲存為常數,而不是直接儲存在方法主體中,但這可由您自行決定。 針對 GetClassNameCore,您無需當地語系化此字串。 每當 UI 自動化用戶端需要當地語系化字串時,都會使用 LocalizedControlType 屬性,而不是 ClassName。
GetAutomationControlType
某些輔助技術在回報 UI 自動化樹狀結構中的項目特徵時,會直接使用 GetAutomationControlType 值,作為 UI 自動化 Name 以外的附加資訊。 如果您的控制項與做為衍生來源的控制項明顯不同,且您想要回報的控制項類型不同於該控制項所使用之基底對等類別所回報的控制項類型,則必須實作一個對等,並在對等實作中覆寫 GetAutomationControlTypeCore。 如果您的衍生來源是通用的基底類別 (例如 ItemsControl 或 ContentControl),而該基底對等並未提供有關控制項類型的精確資訊,這點就特別重要。
GetAutomationControlTypeCore 的實作會傳回 AutomationControlType 值來描述您的控制項。 儘管可以傳回 AutomationControlType.Custom,但如果其中一個特定的控制項類型能夠準確描述控制項的主要場景,則應傳回該控制項類型。 以下是範例。
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Spinner;
}
注意
除非您指定 AutomationControlType.Custom,否則您不需要實作 GetLocalizedControlTypeCore 來向用戶端提供 LocalizedControlType 屬性值。 UI 自動化通用基礎結構會為的每個可能的 AutomationControlType 值 (除了 AutomationControlType.Custom 以外) 提供翻譯後的字串。
GetPattern 和 GetPatternCore
對等的 GetPatternCore 實作會傳回支援輸入參數中所請求之模式的物件。 具體來說,UI 自動化用戶端會呼叫一個轉送至提供者之 GetPattern 方法的方法,並指定用來命名所請求模式的 PatternInterface 列舉值。 您對 GetPatternCore 的覆寫應傳回用來實作指定模式的物件。 該物件就是對等本身,因為只要對等回報它支援某種模式,就應該實作對應的模式介面。 如果您的對等沒有特定模式的自訂實作,但您知道該對等的基底確實實作了該模式,則可以從 GetPatternCore 呼叫基底類型的 GetPatternCore 實作。 如果對等不支援某個模式,則該對等的 GetPatternCore 應傳回 null。 不過,針對任何不支援的模式,您通常會依賴呼叫基底實作來傳回 null,而不是直接從您的實作傳回 null。
當模式受支援時,GetPatternCore 實作可傳回 this 或 Me。 我們期望 UI 自動化用戶端在 GetPattern 回傳值不為 null 的情況下,將其轉換為請求的模式介面。
如果對等類別繼承自另一個對等,且基底類別已處理所有必要的支援和模式回報,則無需實作 GetPatternCore。 例如,如果您正作實作一個衍生自 RangeBase 的範圍控制項,而您的對等衍生自 RangeBaseAutomationPeer,則該對等會針對 PatternInterface.RangeValue 傳回自身,並擁有支援該模式之 IRangeValueProvider 介面的運作中實作。
雖然不是常值程式碼,但此範例近似於 RangeBaseAutomationPeer 中已存在的 GetPatternCore 實作。
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 列舉值,而這就是 UI 自動化用戶端透過 GetPattern 呼叫請求模式的方式。
對等可回報自己支援多個模式。 如果是這樣,則覆寫應包含每個受支援的 PatternInterface 值的傳回路徑邏輯,並在每個相符案例中傳回對等。 我們期望呼叫端一次只請求一個介面,並由呼叫端決定是否轉換為預期的介面。
以下是一個自訂對等的 GetPatternCore 覆寫範例。 此範例回報了對兩種模式的支援:IRangeValueProvider 和 IToggleProvider。 這裡的控制項是一個媒體顯示控制項,可顯示為全螢幕 (切換模式),並有一個進度列,可以讓使用者在其中選取位置 (範圍控制項)。 這段程式碼源自於 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.CreatePeer.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);
}
其他 Core 方法
您的控制項可能需要在主要場景中支援鍵盤等效裝置;如需進一步了解鍵盤等效裝置的必要性,請參閱鍵盤協助工具。 實作按鍵支援必然是控制項程式碼 (而不是對等程式碼) 的一部分,因為這是控制項邏輯的一部分,但您的對等類別應覆寫 GetAcceleratorKeyCore 和 GetAccessKeyCore 方法,以便向 UI 自動化用戶端回報使用了哪些按鍵。 考慮到回報按鍵資訊的字串可能需要當地語系化,因此該字串應來自資源,而不應該是硬式編碼的字串。
如果您要為支援集合的類別提供對等,最好從已經支援此類集合的函式類別和對等類別衍生。 如果您無法這樣做,則維護子集合的控制項對等可能必須覆寫與集合相關的對等方法 GetChildrenCore,才能正確地向 UI 自動化樹狀結構回報父子關聯性。
請實作 IsContentElementCore 和 IsControlElementCore 方法,以指出您的控制項是否包含資料內容、或在使用者介面中擔任互動角色 (或兩者兼備)。 根據預設,這兩個方法皆會傳回 true。 這些設定能改善輔助技術 (例如螢幕助讀程式) 的可用性,這些工具可以使用這些方法來篩選自動化樹狀結構。 如果您的 GetPatternCore 方法將模式處理傳送至子元素對等,則子元素對等的 IsControlElementCore 方法可能會傳回 false,以隱藏自動化樹狀結構中的子元素對等。
某些控制項可能支援標籤場景,其中會有一個文字標籤組件用於提供非文字組件的資訊,或是有一個控制項用於與 UI 中的另一個控制項維持已知的標籤關聯性。 如果可以提供基於類別的實用行為,則可以覆寫 GetLabeledByCore 來提供此行為。
GetBoundingRectangleCore 和 GetClickablePointCore 主要用於自動化測試場景。 如果您要支援控制項的自動化測試,可能需要覆寫這些方法。 這可能是範圍類型控制項所需要的,因為使用者在座標空間中的點擊位置會對範圍產生不同的影響,因此在這種情況下不能只建議單點。 例如,預設的 ScrollBar 自動化對等會覆寫 GetClickablePointCore,以傳回「非數值」的 Point 值。
GetLiveSettingCore 會影響 UI 自動化的 LiveSetting 控制項預設值。 如果您希望控制項傳回 AutomationLiveSetting.Off 以外的值,您可能需要覆寫此值。 如要進一步了解 LiveSetting 的含義,請參閱 AutomationProperties.LiveSetting。
如果控制項擁有可對應至 AutomationOrientation 的可設定方向屬性,您可以覆寫 GetOrientationCore。 ScrollBarAutomationPeer 和 SliderAutomationPeer 類別可執行此操作。
FrameworkElementAutomationPeer 中的基底實作
FrameworkElementAutomationPeer 的基底實作提供了一些 UI 自動化資訊,這些資訊可根據在架構層級上定義的各種版面配置和行為屬性來解釋。
- GetBoundingRectangleCore:根據已知的版面配置特性,傳回 Rect 結構。 如果 IsOffscreen 為 true,則傳回 0 值 Rect。
- GetClickablePointCore:只要有非零 BoundingRectangle,就會根據已知的版面配置特性傳回 Point 結構。
- GetNameCore:無法在此總結的廣泛行為;請參閱 GetNameCore。 基本上,它會嘗試對 ContentControl 或含有內容之相關類別的任何已知內容進行字串轉換。 此外,如果存在 LabeledBy 的值,則該項目的 Name 值將用來當作 Name 。
- HasKeyboardFocusCore:根據擁有者的 FocusState 和 IsEnabled 屬性進行評估。 非控制項元素一律會傳回 false。
- IsEnabledCore:如果是 Control,則根據擁有者的 IsEnabled 屬性進行評估。 非控制項元素一律會傳回 true。 這並不代表擁有者在傳統互動意義上已啟用,而是代表雖然擁有者沒有 IsEnabled 屬性,但對等仍已啟用。
- IsKeyboardFocusableCore:如果擁有者是 Control,則傳回 true;否則傳回 false。
- IsOffscreenCore:擁有者元素或任何其父元素上的 Visibility 為 Collapsed,相等於 IsOffscreen 的值為 true。 例外:即使其擁有者的父代不可見,Popup 仍然可以是可見物件。
- SetFocusCore:呼叫 Focus。
- GetParent:從擁有者呼叫 FrameworkElement.Parent,並尋找適當的對等。 這不是 "Core" 方法的覆寫對,因此您無法變更此行為。
注意
預設 UWP 對等會使用實作 UWP 的內部原生程式碼 (而不一定使用實際的 UWP 程式碼) 來實作行為。 您無法透過 Common Language Runtime (CLR) 反射或其他技術,查看實作的程式碼或邏輯。 您也不會看到基底對等行為之子類別專用覆寫的不同參考頁面。 例如,TextBoxAutomationPeer 的 GetNameCore 可能會有其他行為,但 AutomationPeer.GetNameCore 參考頁面不會對此進行描述,且 TextBoxAutomationPeer.GetNameCore 沒有參考頁面。 甚至沒有 TextBoxAutomationPeer.GetNameCore 參考頁面。 請改為閱讀最相關對等類別的參考主題,並在「備註」部分尋找實作注意事項。
對等和 AutomationProperties
自動化對等應為控制項的協助工具相關資訊提供適當的預設值。 請注意,使用該控制項的任何應用程式程式碼都可以在控制項執行個體上加入 AutomationProperties 附加屬性值,藉此覆寫某些行為。 呼叫端可針對預設控制項或自訂控制項執行此操作。 例如,下列 XAML 會建立有兩個自訂 UI 自動化屬性的按鈕:<Button AutomationProperties.Name="Special" AutomationProperties.HelpText="This is a special button."/>
。
如需 AutomationProperties 附加屬性的詳細資訊,請參閱基本的協助工具資訊。
有些 AutomationPeer 方法之所以存在,是為了履行有關 UI 自動化提供者應回報資訊的一般協定,但這些方法通常不會在控制項對等中實作。 原因在於,該資訊預期應由 AutomationProperties 值提供,該值套用於使用特定 UI 內部控制項的應用程式程式碼。 例如,大多數應用程式會透過套用 AutomationProperties.LabeledBy 值,來定義 UI 中兩個不同控制項之間的標籤關聯性。 然而,LabeledByCore 會在用來代表控制項中的資料或項目關係的特定對等中實作,例如使用標頭組件來標記資料欄位組件、使用其容器標記項目或類似的場景。
實作模式
以下說明如何為控制項編寫一個用來實作展開-收合行為的對等,方法是實作展開-收合的控制項模式介面。 每當使用 PatternInterface.ExpandCollapse 的值來呼叫 GetPattern 時,對等都應該傳回自身,以啟用展開-收合行為的協助工具。 接著,對等應繼承該模式的提供者介面 (IExpandCollapseProvider),並為該提供者介面的每個成員提供實作。 在此情況下,介面有三個成員需要覆寫:Expand、Collapse、ExpandCollapseState。
在類別本身的 API 設計中提前規劃協助工具,是很有幫助的。 如果與使用者在 UI 中進行常見互動時可能會請求一種行為,或是有可能透過自動化提供者模式請求該行為,就請一律提供 UI 回應或自動化模式可以呼叫的單一方法。 例如,如果您的控制項具有按鈕組件,而這些組件具有可展開或收合控制項的有線事件處理常式,並具有與這些操作對應的鍵盤對等項目,請讓這些事件處理常式呼叫您從對等中 IExpandCollapseProvider 的Expand 或 Collapse 實作主體內呼叫的相同方法。 使用通用邏輯方法也是一種有用的方法,可確保控制項的視覺狀態已更新,能以統一的方式顯示邏輯狀態,不論叫用行為的方式為何。
典型的實作方法是,由提供者 API 先呼叫 Owner,在執行階段存取控制項執行個體。 接著就可以在該物件上呼叫必要的行為方法。
public class IndexCardAutomationPeer : FrameworkElementAutomationPeer, IExpandCollapseProvider {
private IndexCard ownerIndexCard;
public IndexCardAutomationPeer(IndexCard owner) : base(owner)
{
ownerIndexCard = owner;
}
}
另一種實作方式,是讓控制項本身可以引用其對等。 此模式是從控制項引發自動化事件時的常見模式,因為 RaiseAutomationEvent 方法是一種對等方法。
UI 自動化事件
UI 自動化事件可分類如下。
事件 | 描述 |
---|---|
屬性變更 | 在 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)。 然而,它們是透過原生方法提供這項支援,而所涉及的對等不會注意到 (managed) 繼承中的 ITextProvider 介面。 不過,如果受控或非受控 UI 自動化用戶端向對等查詢模式,則將回報對文字模式的支援,並在呼叫用戶端 API 時提供模式組件的行為。
如果您想要從其中一個 UWP 應用程式文字控制項衍生,並建立從其中一個文字相關對等衍生的自訂對等,請檢查該對等的「備註」部分,以進一步了解模式的任何原生層級支援。 如果您從受控提供者介面實作呼叫基底實作,則可以存取自訂對等中的原生基底行為,但很難修改基底實作的功能,因為對等及其擁有者控制項上的原生介面不會公開。 在一般情況,您應該按原樣使用基底實作 (只叫用基底實作),或是使用您自己的受控程式碼完全替換功能,而不呼叫基底實作。 後者是一個進階方案,您必須非常熟悉控制項所使用的文字服務架構,才能在使用該架構時滿足協助工具需求。
AutomationProperties.AccessibilityView
除了提供自訂對等,您還可以透過在 XAML 中設定 AutomationProperties.AccessibilityView,調整任何控制項執行個體的樹狀結構檢視表示法。 這不會實作為對等類別的一部分,但我們在這裡提及它,是因為它與自訂控制項或自訂範本的整體協助工具支援密切相關。
使用 AutomationProperties.AccessibilityView 的主要情況,是在 UI 介面自動化檢視中刻意省略範本中的某些控制項,因為它們對整個控制項的協助工具檢視沒有太大意義。 若要避免這種情況,請將 AutomationProperties.AccessibilityView 設定為「Raw」。
從自動化對等擲回例外狀況
您為自動化對等支援實作的 API 允許擲回例外狀況。 我們預期任何正在接聽的 UI 自動化用戶端都足夠強大,能夠在大部分例外狀況擲回後繼續運作。 接聽程式很可能正在查看一個完整的自動化樹狀結構,其中包含您自己的應用程式以外的其他應用程式;而僅僅因為樹狀結構的其中一個區域擲回基於對等的例外狀況,就導致整個用戶端崩潰,這樣的用戶端設計是不可接受的。
針對傳入對等的參數,可以對輸入進行驗證;例如,如果傳入的是 null,而這對您的實作來說不是有效值,則會擲回 ArgumentNullException。 不過,如果後續操作是由對等執行,請記住,對等與裝載控制項的互動具有非同步特性。 對等所做的任何動作,不一定會封鎖控制項中的 UI 執行緒 (可能也不應該封鎖)。 因此,您可能會遇到以下情況:在建立對等或首次呼叫自動化對等方法時,物件是可用的或具有某些屬性,但控制項狀態也在此期間發生變化。 在這些情況下,提供者可能會擲回兩個專用例外狀況:
- 如果您無法根據 API 傳遞的原始資訊來存取對等擁有者或相關對等元素,則會擲回 ElementNotAvailableException。 例如,您可能有一個對等正在嘗試執行其方法,但擁有者已從 UI 中刪除,例如已關閉的強制回應對話方塊。 對於非 .NET 用戶端,這會對應至 UIA_E_ELEMENTNOTAVAILABLE。
- 如果仍然存在擁有者,但該擁有者處於 IsEnabled
=
false 等模式,而該模式會阻止對等正在嘗試完成的某些特定程式設計變更,則會擲回 ElementNotEnabledException。 對於非 .NET 用戶端,這會對應至 UIA_E_ELEMENTNOTENABLED。
此外,對等應對它們從其對等支援擲回的例外狀況採取相對保守的態度。 大部分的用戶端都無法處理來自對等的例外狀況,也無法將其轉換成使用者與用戶端互動時可執行的選項。 因此,在某些情況,不採取任何行動、僅在對等實作內攔截例外狀況而不重新擲回,是比每次對等嘗試執行的動作失敗時都擲回例外狀況更好的策略。 此外還要考慮到,大多數 UI 自動化用戶端不是用受控程式碼編寫的。 這類用戶端大多是使用 COM 編寫的,而每當它們呼叫 UI 自動化用戶端方法、並因此存取您的對等時,都會在 HRESULT 中檢查 S_OK。