Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Poznámka:
Tato dokumentace je určená pro vývojáře rozhraní .NET Framework, kteří chtějí používat spravované třídy automatizace uživatelského rozhraní definované v System.Windows.Automation oboru názvů. Nejnovější informace o automatizaci uživatelského rozhraní najdete v tématu Rozhraní API služby Windows Automation: Automatizace uživatelského rozhraní.
Toto téma obsahuje scénáře a vzorový kód, které ukazují, jak a kdy AutomationIdProperty lze použít k vyhledání prvku ve stromu Automatizace uživatelského rozhraní.
AutomationIdProperty jedinečně identifikuje prvek automatizace uživatelského rozhraní od jeho sourozenců. Další informace o identifikátorech vlastností souvisejících s identifikací ovládacích prvků naleznete v tématu Přehled vlastností automatizace uživatelského rozhraní.
Poznámka:
AutomationIdProperty nezaručuje jedinečnou identitu v celém stromu, obvykle potřebuje informace o kontejneru a rozsahu, aby byly použitelné. Aplikace může například obsahovat ovládací prvek nabídky s několika položkami nejvyšší úrovně, které mají také několik podřízených položek. Tyto sekundární položky nabídky mohou být identifikovány obecným schématem, jako je například „Položka1“, „Položka 2“ atd., což umožňuje duplicitní označení podřízených položek nabídky nejvyšší úrovně.
Scénáře
Byly identifikovány tři primární scénáře klientských aplikací pro automatizaci uživatelského rozhraní, které vyžadují použití AutomationIdProperty k dosažení přesných a konzistentních výsledků při hledání prvků.
Poznámka:
AutomationIdProperty podporuje všechny prvky automatizace uživatelského rozhraní v zobrazení ovládacích prvků kromě oken aplikací nejvyšší úrovně, prvky automatizace uživatelského rozhraní odvozené z ovládacích prvků Windows Presentation Foundation (WPF), které nemají ID nebo x:Uid, a prvky automatizace uživatelského rozhraní odvozené z ovládacích prvků Win32, které nemají ID ovládacího prvku.
Použijte jedinečné a zjistitelné AutomationID k lokalizaci konkrétního prvku ve stromu Automatizace uživatelského rozhraní
- Pomocí nástroje, jako je UI Spy, nahlaste prvek uživatelského rozhraní AutomationIdProperty který vás zajímá. Tuto hodnotu pak můžete zkopírovat a vložit do klientské aplikace, jako je testovací skript pro následné automatizované testování. Tento přístup snižuje a zjednodušuje kód potřebný k identifikaci a vyhledání prvku za běhu.
Upozornění
Obecně byste se měli pokusit získat pouze přímé potomky RootElement. Hledání potomků může iterovat stovky nebo dokonce tisíce prvků, což může mít za následek přetečení zásobníku. Pokud se pokoušíte získat konkrétní prvek na nižší úrovni, měli byste začít hledání z okna aplikace nebo z kontejneru na nižší úrovni.
///--------------------------------------------------------------------
/// <summary>
/// Finds all elements in the UI Automation tree that have a specified
/// AutomationID.
/// </summary>
/// <param name="targetApp">
/// The root element from which to start searching.
/// </param>
/// <param name="automationID">
/// The AutomationID value of interest.
/// </param>
/// <returns>
/// The collection of UI Automation elements that have the specified
/// AutomationID value.
/// </returns>
///--------------------------------------------------------------------
private AutomationElementCollection FindElementFromAutomationID(AutomationElement targetApp,
string automationID)
{
return targetApp.FindAll(
TreeScope.Descendants,
new PropertyCondition(AutomationElement.AutomationIdProperty, automationID));
}
'''--------------------------------------------------------------------
''' <summary>
''' Finds all elements in the UI Automation tree that have a specified
''' AutomationID.
''' </summary>
''' <param name="targetApp">
''' The root element from which to start searching.
''' </param>
''' <param name="automationID">
''' The AutomationID value of interest.
''' </param>
''' <returns>
''' The collection of automation elements that have the specified
''' AutomationID value.
''' </returns>
'''--------------------------------------------------------------------
Private Function FindElementFromAutomationID( _
ByVal targetApp As AutomationElement, _
ByVal automationID As String) As AutomationElementCollection
Return targetApp.FindAll( _
TreeScope.Descendants, _
New PropertyCondition( _
AutomationElement.AutomationIdProperty, automationID))
End Function 'FindElementFromAutomationID
Použití trvalé cesty k návratu na dříve identifikovaný AutomationElement
- Klientské aplikace, od jednoduchých testovacích skriptů po robustní nástroje pro záznam a přehrávání, mohou vyžadovat přístup k prvkům, které nejsou momentálně instancovány, například dialog pro otevření souboru nebo položka nabídky, a proto neexistují ve stromu automatizace uživatelského rozhraní. Tyto prvky je možné vytvořit pouze pomocí reprodukcí nebo přehráním určité posloupnosti akcí uživatelského rozhraní prostřednictvím použití vlastností automatizace uživatelského rozhraní, jako jsou AutomationID, vzory ovládacích prvků a naslouchací procesy událostí.
///--------------------------------------------------------------------
/// <summary>
/// Creates a UI Automation thread.
/// </summary>
/// <param name="sender">Object that raised the event.</param>
/// <param name="e">Event arguments.</param>
/// <remarks>
/// UI Automation must be called on a separate thread if the client
/// application itself could become a target for event handling.
/// For example, focus tracking is a desktop event that could involve
/// the client application.
/// </remarks>
///--------------------------------------------------------------------
private void CreateUIAThread(object sender, EventArgs e)
{
// Start another thread to do the UI Automation work.
ThreadStart threadDelegate = new ThreadStart(CreateUIAWorker);
Thread workerThread = new Thread(threadDelegate);
workerThread.Start();
}
///--------------------------------------------------------------------
/// <summary>
/// Delegated method for ThreadStart. Creates a UI Automation worker
/// class that does all UI Automation related work.
/// </summary>
///--------------------------------------------------------------------
public void CreateUIAWorker()
{
uiautoWorker = new FindByAutomationID(targetApp);
}
private FindByAutomationID uiautoWorker;
'''--------------------------------------------------------------------
''' <summary>
''' Creates a UI Automation thread.
''' </summary>
''' <param name="sender">Object that raised the event.</param>
''' <param name="e">Event arguments.</param>
''' <remarks>
''' UI Automation must be called on a separate thread if the client
''' application itself could become a target for event handling.
''' For example, focus tracking is a desktop event that could involve
''' the client application.
''' </remarks>
'''--------------------------------------------------------------------
Private Sub CreateUIAThread(ByVal sender As Object, ByVal e As EventArgs)
' Start another thread to do the UI Automation work.
Dim threadDelegate As New ThreadStart(AddressOf CreateUIAWorker)
Dim workerThread As New Thread(threadDelegate)
workerThread.Start()
End Sub
'''--------------------------------------------------------------------
''' <summary>
''' Delegated method for ThreadStart. Creates a UI Automation worker
''' class that does all UI Automation related work.
''' </summary>
'''--------------------------------------------------------------------
Public Sub CreateUIAWorker()
uiautoWorker = New UIAWorker(targetApp)
End Sub
Private uiautoWorker As UIAWorker
///--------------------------------------------------------------------
/// <summary>
/// Function to playback through a series of recorded events calling
/// a WriteToScript function for each event of interest.
/// </summary>
/// <remarks>
/// A major drawback to using AutomationID for recording user
/// interactions in a volatile UI is the probability of catastrophic
/// change in the UI. For example, the //Processes// dialog where items
/// in the listbox container can change with no input from the user.
/// This mandates that a record and playback application must be
/// reliant on the tester owning the UI being tested. In other words,
/// there has to be a contract between the provider and client that
/// excludes uncontrolled, external applications. The added benefit
/// is the guarantee that each control in the UI should have an
/// AutomationID assigned to it.
///
/// This function relies on a UI Automation worker class to create
/// the System.Collections.Generic.Queue object that stores the
/// information for the recorded user interactions. This
/// allows post-processing of the recorded items prior to actually
/// writing them to a script. If this is not necessary the interaction
/// could be written to the script immediately.
/// </remarks>
///--------------------------------------------------------------------
private void Playback(AutomationElement targetApp)
{
AutomationElement element;
foreach(ElementStore storedItem in uiautoWorker.elementQueue)
{
PropertyCondition propertyCondition =
new PropertyCondition(
AutomationElement.AutomationIdProperty, storedItem.AutomationID);
// Confirm the existence of a control.
// Depending on the controls and complexity of interaction
// this step may not be necessary or may require additional
// functionality. For example, to confirm the existence of a
// child menu item that had been invoked the parent menu item
// would have to be expanded.
element = targetApp.FindFirst(TreeScope.Descendants, propertyCondition);
if(element == null)
{
// Control not available, unable to continue.
// TODO: Handle error condition.
return;
}
WriteToScript(storedItem.AutomationID, storedItem.EventID);
}
}
///--------------------------------------------------------------------
/// <summary>
/// Generates script code and outputs the code to a text control in
/// the client.
/// </summary>
/// <param name="automationID">
/// The AutomationID of the current control.
/// </param>
/// <param name="eventID">
/// The event recorded on that control.
/// </param>
///--------------------------------------------------------------------
private void WriteToScript(string automationID, string eventID)
{
// Script code would be generated and written to an output file
// as plain text at this point, but for the
// purposes of this example we just write to the console.
Console.WriteLine(automationID + " - " + eventID);
}
'''--------------------------------------------------------------------
''' <summary>
''' Function to playback through a series of recorded events calling
''' a WriteToScript function for each event of interest.
''' </summary>
''' <remarks>
''' A major drawback to using AutomationID for recording user
''' interactions in a volatile UI is the probability of catastrophic
''' change in the UI. For example, the 'Processes' dialog where items
''' in the listbox container can change with no input from the user.
''' This mandates that a record and playback application must be
''' reliant on the tester owning the UI being tested. In other words,
''' there has to be a contract between the provider and client that
''' excludes uncontrolled, external applications. The added benefit
''' is the guarantee that each control in the UI should have an
''' AutomationID assigned to it.
'''
''' This function relies on a UI Automation worker class to create
''' the System.Collections.Generic.Queue object that stores the
''' information for the recorded user interactions. This
''' allows post-processing of the recorded items prior to actually
''' writing them to a script. If this is not necessary the interaction
''' could be written to the script immediately.
''' </remarks>
'''--------------------------------------------------------------------
Private Sub Playback(ByVal targetApp As AutomationElement)
Dim element As AutomationElement
Dim storedItem As ElementStore
For Each storedItem In uiautoWorker.elementQueue
Dim propertyCondition As New PropertyCondition( _
AutomationElement.AutomationIdProperty, storedItem.AutomationID)
' Confirm the existence of a control.
' Depending on the controls and complexity of interaction
' this step may not be necessary or may require additional
' functionality. For example, to confirm the existence of a
' child menu item that had been invoked the parent menu item
' would have to be expanded.
element = targetApp.FindFirst( _
TreeScope.Descendants, propertyCondition)
If element Is Nothing Then
' Control not available, unable to continue.
' TODO: Handle error condition.
Return
End If
WriteToScript(storedItem.AutomationID, storedItem.EventID)
Next storedItem
End Sub
'''--------------------------------------------------------------------
''' <summary>
''' Generates script code and outputs the code to a text control in
''' the client.
''' </summary>
''' <param name="automationID">
''' The AutomationID of the current control.
''' </param>
''' <param name="eventID">
''' The event recorded on that control.
''' </param>
'''--------------------------------------------------------------------
Private Sub WriteToScript( _
ByVal automationID As String, ByVal eventID As String)
' Script code would be generated and written to an output file
' as plain text at this point, but for the
' purposes of this example we just write to the console.
Console.WriteLine(automationID + " - " + eventID)
End Sub
Použijte relativní cestu k vrácení se k dříve identifikovanému AutomationElement
- Za určitých okolností, protože AutomationID je zaručeno, že je jedinečný pouze mezi elementy na stejné úrovni, může mít více prvků ve stromu automatizace uživatelského rozhraní stejné hodnoty vlastností AutomationID. V těchto situacích lze prvky jednoznačně identifikovat na základě rodiče a, pokud je to nutné, také prarodiče. Vývojář může například poskytnout nabídku s více položkami, z nichž každá obsahuje další podřízené položky. Tyto podřízené položky jsou identifikovány sekvenčními AutomationID, jako například "Item1", "Item2" a tak dále. Každá položka nabídky by pak mohla být jedinečně identifikována jeho ID AutomationID spolu s Id AutomationID nadřazeného objektu a v případě potřeby jeho dědečkem.