WPF 自訂控制項的 UI 自動化
消費者介面自動化提供單一的一般化介面,讓自動化用戶端可用來檢查或操作各種平臺和架構的使用者介面。 消費者介面自動化可讓品質保證(測試)程式碼和協助工具應用程式,例如螢幕助讀程式檢查使用者介面元素,並從其他程式碼模擬使用者互動。 如需跨所有平臺消費者介面自動化的相關資訊,請參閱協助工具。
本主題說明如何針對在 WPF 應用程式中執行的自訂控制項,實作伺服器端 UI 自動化提供者。 WPF 支援透過平行使用者介面元素樹狀結構的對等自動化物件的樹狀結構來消費者介面自動化。 提供協助工具功能的測試程式碼和應用程式可以直接使用自動化對等物件(適用于同進程程式碼),或透過消費者介面自動化提供的一般化介面。
自動化對等類別
WPF 控制項支援透過衍生自 AutomationPeer 的對等類別樹狀結構消費者介面自動化。 依照慣例,對等類別名稱會以控制項類別名稱開始,並以 "AutomationPeer" 結束。 例如, ButtonAutomationPeer 是控制項類別的 Button 對等類別。 對等類別大致相當於消費者介面自動化控制項類型,但專屬於 WPF 元素。 透過 消費者介面自動化 介面存取 WPF 應用程式的自動化程式碼不會直接使用自動化對等,但相同進程空間中的自動化程式碼可以直接使用自動化對等。
內建自動化對等類別
如果元素接受來自使用者的介面活動,或包含螢幕助讀應用程式使用者所需的資訊,便會實作自動化對等類別。 並非所有 WPF 視覺元素都有自動化對等。 實作自動化對等的類別範例包括 Button 、 TextBox 和 Label 。 未實作自動化對等的類別範例是衍生自 Decorator 的類別,例如 Border , 和 類別, Panel 例如 Grid 和 Canvas 。
基 Control 類沒有對應的對等類別。 如果您需要對等類別來對應至衍生自 Control 的自訂控制項,您應該從 FrameworkElementAutomationPeer 衍生自訂對等類別。
衍生對等的安全性考量
自動化對等必須在部分信任的環境中執行。 UIAutomationClient 組件中的程式碼並沒有針對在部分信任的環境中執行進行設定,因此自動化對等程式碼不應該參考該組件。 您應該改為使用 UIAutomationTypes 組件中的類別。 例如,您應該使用 AutomationElementIdentifiers UIAutomationTypes 元件中的 類別,該元件對應至 AutomationElement UIAutomationClient 元件中的類別。 在自動化對等程式碼中參考 UIAutomationTypes 組件是安全的。
對等瀏覽
尋找自動化對等之後,同進程程式碼可以藉由呼叫 物件的 GetChildren 和 GetParent 方法來巡覽對等樹狀結構。 對等方法的 GetChildrenCore 實作支援在 控制項內的 WPF 元素之間流覽。 UI 自動化系統會呼叫此方法來建置控制項內所包含之子元素的樹狀結構,例如清單方塊中的清單項目。 預設 UIElementAutomationPeer.GetChildrenCore 方法會周遊專案的視覺化樹狀結構,以建置自動化對等的樹狀結構。 自訂控制項會覆寫此方法,以將子系元素公開給自動化用戶端,並傳回能傳達資訊或允許使用者互動的元素自動化對等。
衍生對等中的自訂
衍生自 UIElement 並 ContentElement 包含受保護虛擬方法 OnCreateAutomationPeer 的所有類別。 WPF 呼叫 OnCreateAutomationPeer 以取得每個控制項的自動化對等物件。 自動化程式碼可以使用對等來取得控制項特性和功能的相關資訊,並模擬互動式使用。 支援自動化的自訂控制項必須覆寫 OnCreateAutomationPeer 並傳回衍生自 AutomationPeer 之類別的實例。 例如,如果自訂控制項衍生自 ButtonBase 類別,則 傳 OnCreateAutomationPeer 回的物件應該衍生自 ButtonBaseAutomationPeer 。
實作自訂控制項時,您必須從描述您自訂控制項唯一且特定之行為的基底自動化對等類別,覆寫 "Core" 方法。
覆寫 OnCreateAutomationPeer
OnCreateAutomationPeer覆寫自訂控制項的 方法,使其傳回提供者物件,該物件必須直接或間接衍生自 AutomationPeer 。
覆寫 GetPattern
自動化對等可簡化伺服器端消費者介面自動化提供者的一些實作層面,但自訂控制項自動化對等仍必須處理模式介面。 如同非 WPF 提供者,對等會藉由在 命名空間中 System.Windows.Automation.Provider 提供介面的實作來支援控制項模式,例如 IInvokeProvider 。 控制項模式介面可以由對等本身實作,或是由另一個物件實作。 對等的 實 GetPattern 作會傳回支援指定模式的物件。 消費者介面自動化程式碼會呼叫 方法, GetPattern 並指定 PatternInterface 列舉值。 的覆寫 GetPattern 應該會傳回實作指定模式的物件。 如果您的控制項沒有模式的自訂實作,您可以呼叫基底類型的 實 GetPattern 作,以擷取其實作,如果此控制項類型不支援模式,則為 Null。 例如,自訂 NumericUpDown 控制項可以設定為範圍內的值,因此其消費者介面自動化對等會實作 IRangeValueProvider 介面。 下列範例示範如何覆寫對等的 GetPattern 方法以回應 PatternInterface.RangeValue 值。
public override object GetPattern(PatternInterface patternInterface)
{
if (patternInterface == PatternInterface.RangeValue)
{
return this;
}
return base.GetPattern(patternInterface);
}
Public Overrides Function GetPattern(ByVal patternInterface As PatternInterface) As Object
If patternInterface = PatternInterface.RangeValue Then
Return Me
End If
Return MyBase.GetPattern(patternInterface)
End Function
GetPattern方法也可以將子項目指定為模式提供者。 下列程式碼示範如何將 ItemsControl 捲動模式處理傳送至其內部 ScrollViewer 控制項的對等。
public override object GetPattern(PatternInterface patternInterface)
{
if (patternInterface == PatternInterface.Scroll)
{
ItemsControl owner = (ItemsControl) base.Owner;
// ScrollHost is internal to the ItemsControl class
if (owner.ScrollHost != null)
{
AutomationPeer peer = UIElementAutomationPeer.CreatePeerForElement(owner.ScrollHost);
if ((peer != null) && (peer is IScrollProvider))
{
peer.EventsSource = this;
return (IScrollProvider) peer;
}
}
}
return base.GetPattern(patternInterface);
}
Public Class Class1
Public Overrides Function GetPattern(ByVal patternInterface__1 As PatternInterface) As Object
If patternInterface1 = PatternInterface.Scroll Then
Dim owner As ItemsControl = DirectCast(MyBase.Owner, ItemsControl)
' ScrollHost is internal to the ItemsControl class
If owner.ScrollHost IsNot Nothing Then
Dim peer As AutomationPeer = UIElementAutomationPeer.CreatePeerForElement(owner.ScrollHost)
If (peer IsNot Nothing) AndAlso (TypeOf peer Is IScrollProvider) Then
peer.EventsSource = Me
Return DirectCast(peer, IScrollProvider)
End If
End If
End If
Return MyBase.GetPattern(patternInterface1)
End Function
End Class
若要指定模式處理的子項目,此程式碼會取得子項目物件、使用 CreatePeerForElement 方法建立對等、將新對等的 屬性設定 EventsSource 為目前對等,並傳回新的對等。 在子項目上設定 EventsSource 可防止子項目出現在自動化對等樹狀結構中,並將子項目引發的所有事件指定為源自 于 中指定的 EventsSource 控制項。 控制項 ScrollViewer 不會出現在自動化樹狀結構中,而且其產生的捲動事件似乎來自 ItemsControl 物件。
覆寫 "Core" 方法
自動化程式碼會呼叫對等類別的公用方法,來取得控制項的相關資訊。 若要提供您控制項的相關資訊,請在您的控制項實作和由基底自動化對等類別所提供的不同時,覆寫所有名稱以 "Core" 為結尾的方法。 您的控制項至少必須實 GetClassNameCore 作 和 GetAutomationControlTypeCore 方法,如下列範例所示。
protected override string GetClassNameCore()
{
return "NumericUpDown";
}
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Spinner;
}
Protected Overrides Function GetClassNameCore() As String
Return "NumericUpDown"
End Function
Protected Overrides Function GetAutomationControlTypeCore() As AutomationControlType
Return AutomationControlType.Spinner
End Function
的 實作 GetAutomationControlTypeCore 會藉由傳 ControlType 回 值來描述您的控制項。 雖然您可以傳回 ControlType.Custom ,但如果控制項正確描述控制項,您應該傳回其中一個更特定的控制項類型。 的傳回值 ControlType.Custom 需要額外的工作,提供者才能實作消費者介面自動化,而且消費者介面自動化用戶端產品無法預期控制項結構、鍵盤互動和可能的控制項模式。
實作 IsContentElementCore 和 IsControlElementCore 方法,以指出您的控制項是否包含資料內容,或履行使用者介面中的互動式角色(或兩者)。 根據預設,這兩個方法皆會傳回 true
。 這些設定能改善自動化工具 (例如螢幕助讀程式) 的可用性,這些工具可以使用這些方法來篩選自動化樹狀結構。 GetPattern如果您的方法會將模式處理傳送至子項目對等,則子項目對等 IsControlElementCore 的 方法可能會傳回 false,以隱藏自動化樹狀結構中的子項目對等。 例如,捲動是由 ScrollViewer 處理,而 的自動化對等 PatternInterface.Scroll 是由 與 ListBoxAutomationPeer 相關聯 之 ScrollViewerAutomationPeer 的 方法傳回 GetPattern 。 ListBox因此,的 IsControlElementCoreScrollViewerAutomationPeer 方法會 false
傳回 ,讓 ScrollViewerAutomationPeer 不會出現在自動化樹狀結構中。
您的自動化對等應該為您的控制項提供適當的預設值。 請注意,參考控制項的 XAML 可以藉由包含 AutomationProperties 屬性來覆寫核心方法的對等實作。 例如,下列 XAML 會建立具有兩個自訂消費者介面自動化屬性的按鈕。
<Button AutomationProperties.Name="Special"
AutomationProperties.HelpText="This is a special button."/>
實作模式提供者
如果擁有專案直接衍生自 Control ,則明確宣告自訂提供者所實作的介面。 例如,下列程式碼會宣告 實 Control 作範圍值的 對等。
public class RangePeer1 : FrameworkElementAutomationPeer, IRangeValueProvider { }
Public Class RangePeer1
Inherits FrameworkElementAutomationPeer
Implements IRangeValueProvider
End Class
如果擁有控制項衍生自特定類型的控制項,例如 RangeBase ,則對等可以衍生自對等衍生的對等類別。 在此情況下,對等會衍生自 RangeBaseAutomationPeer ,其提供 的基底實作 IRangeValueProvider 。 下列程式碼顯示這種對等的宣告。
public class RangePeer2 : RangeBaseAutomationPeer { }
Public Class RangePeer2
Inherits RangeBaseAutomationPeer
End Class
如需實作範例,請參閱 實作和取用 NumericUpDown 自訂控制項的 C# 或 Visual Basic 原始程式碼。
引發事件
自動化用戶端可以訂閱自動化事件。 自訂控制項必須呼叫 RaiseAutomationEvent 方法來報告控制項狀態的變更。 同樣地,當屬性值變更時,呼叫 RaisePropertyChangedEvent 方法。 下列程式碼示範如何從控制項程式碼內取得對等物件,並呼叫方法以引發事件。 做為最佳化的手段,程式碼會判斷此事件類型是否有任何接聽程式。 只在有接聽程式的情況下引發事件,可以避免不必要的額外負荷並協助保持控制項的反應性。
if (AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged))
{
NumericUpDownAutomationPeer peer =
UIElementAutomationPeer.FromElement(nudCtrl) as NumericUpDownAutomationPeer;
if (peer != null)
{
peer.RaisePropertyChangedEvent(
RangeValuePatternIdentifiers.ValueProperty,
(double)oldValue,
(double)newValue);
}
}
If AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged) Then
Dim peer As NumericUpDownAutomationPeer = TryCast(UIElementAutomationPeer.FromElement(nudCtrl), NumericUpDownAutomationPeer)
If peer IsNot Nothing Then
peer.RaisePropertyChangedEvent(RangeValuePatternIdentifiers.ValueProperty, CDbl(oldValue), CDbl(newValue))
End If
End If
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應