编码 UI 无法在展开的行中找到控件
Coded UI Unable to locate controls in expanded rows
与 this question 类似,我正在尝试开发编码 UI 测试,它需要对位于 WPF 行(行详细信息)中的某些控件执行一些断言。不幸的是,Coded UI 检查器似乎无法在展开的行中找到任何控件,因为它将这些控件标识为自定义控件 (Uia.DataGridDetailsPresenter) 的子控件,而自定义控件是该行。
此网格的应用程序 xaml 非常简单,如下所示。
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<TextBlock Text="{Binding Details}" Margin="10" />
</DataTemplate>
</DataGrid.RowDetailsTemplate>
有没有人设法访问以前在编码 UI 测试中使用的行详细信息?
我有同样的问题,编码 UI 检查员看到 Uia.DataGridDetailsPresenter 并且它是 children,但在测试期间无法使用它们 运行。
嗯,您的应用程序可能有问题,此 DataGrid 未发布用于编码 ui 自动化。我对 TabPage 内容也有同样的问题。
如果您想知道,Coded UI 在 Wpf 应用程序中看到什么执行此代码,您将在输出中得到一些元素映射 - 复制到 excel。如果这找到了您需要的控件,那么您的测试也应该找到它们。
/*
* Method used for get map of element and it's children
* element - element whose children you want to explore
* comma - use empty string - ""
*/
public void getMap(WpfControl element, String comma)
{
comma = comma + "\t";
foreach (Object child in element.GetChildren())
{
WpfControl childAsWpf = child as WpfControl;
if (childAsWpf != null && !(element is WpfListItem))
{
logElementInfo(childAsWpf, comma);
getMap(childAsWpf, comma);
}
else
{
System.Diagnostics.Debug.WriteLine("--------- object: {0}; type: {1}", child, child.GetType());
}
}
}
// logs element info in Output
private void logElementInfo(WpfControl element, String comma)
{
System.Diagnostics.Debug.WriteLine("{0}AutomationId: {1}, ClassName: {2}, ControlType: Wpf{3}", comma, element.AutomationId, element.ClassName, element.ControlType);
}
我最终通过编写自己的 DataGrid 控件解决了这个问题,该控件公开了所需的自动化对等项。
通用自动化同行
class GenericAutomationPeer : UIElementAutomationPeer
{
public GenericAutomationPeer(UIElement owner)
: base(owner)
{
}
protected override List<AutomationPeer> GetChildrenCore()
{
List<AutomationPeer> list = base.GetChildrenCore();
list.AddRange(GetChildPeers(Owner));
return list;
}
private List<AutomationPeer> GetChildPeers(UIElement element)
{
List<AutomationPeer> automationPeerList = new List<AutomationPeer>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
UIElement child = VisualTreeHelper.GetChild(element, i) as UIElement;
if (child != null)
{
AutomationPeer childPeer = UIElementAutomationPeer.CreatePeerForElement(child);
if (childPeer != null)
{
automationPeerList.Add(childPeer);
}
else
{
automationPeerList.AddRange(GetChildPeers(child));
}
}
}
return automationPeerList;
}
}
自定义数据网格
public class CustomDataGrid : DataGrid
{
//Override automation peer that the base class provides as it doesn't expose automation peers for the row details
protected override AutomationPeer OnCreateAutomationPeer()
{
return new GenericAutomationPeer(this);
}
}
与 this question 类似,我正在尝试开发编码 UI 测试,它需要对位于 WPF 行(行详细信息)中的某些控件执行一些断言。不幸的是,Coded UI 检查器似乎无法在展开的行中找到任何控件,因为它将这些控件标识为自定义控件 (Uia.DataGridDetailsPresenter) 的子控件,而自定义控件是该行。
此网格的应用程序 xaml 非常简单,如下所示。
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<TextBlock Text="{Binding Details}" Margin="10" />
</DataTemplate>
</DataGrid.RowDetailsTemplate>
有没有人设法访问以前在编码 UI 测试中使用的行详细信息?
我有同样的问题,编码 UI 检查员看到 Uia.DataGridDetailsPresenter 并且它是 children,但在测试期间无法使用它们 运行。
嗯,您的应用程序可能有问题,此 DataGrid 未发布用于编码 ui 自动化。我对 TabPage 内容也有同样的问题。
如果您想知道,Coded UI 在 Wpf 应用程序中看到什么执行此代码,您将在输出中得到一些元素映射 - 复制到 excel。如果这找到了您需要的控件,那么您的测试也应该找到它们。
/*
* Method used for get map of element and it's children
* element - element whose children you want to explore
* comma - use empty string - ""
*/
public void getMap(WpfControl element, String comma)
{
comma = comma + "\t";
foreach (Object child in element.GetChildren())
{
WpfControl childAsWpf = child as WpfControl;
if (childAsWpf != null && !(element is WpfListItem))
{
logElementInfo(childAsWpf, comma);
getMap(childAsWpf, comma);
}
else
{
System.Diagnostics.Debug.WriteLine("--------- object: {0}; type: {1}", child, child.GetType());
}
}
}
// logs element info in Output
private void logElementInfo(WpfControl element, String comma)
{
System.Diagnostics.Debug.WriteLine("{0}AutomationId: {1}, ClassName: {2}, ControlType: Wpf{3}", comma, element.AutomationId, element.ClassName, element.ControlType);
}
我最终通过编写自己的 DataGrid 控件解决了这个问题,该控件公开了所需的自动化对等项。
通用自动化同行
class GenericAutomationPeer : UIElementAutomationPeer
{
public GenericAutomationPeer(UIElement owner)
: base(owner)
{
}
protected override List<AutomationPeer> GetChildrenCore()
{
List<AutomationPeer> list = base.GetChildrenCore();
list.AddRange(GetChildPeers(Owner));
return list;
}
private List<AutomationPeer> GetChildPeers(UIElement element)
{
List<AutomationPeer> automationPeerList = new List<AutomationPeer>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
UIElement child = VisualTreeHelper.GetChild(element, i) as UIElement;
if (child != null)
{
AutomationPeer childPeer = UIElementAutomationPeer.CreatePeerForElement(child);
if (childPeer != null)
{
automationPeerList.Add(childPeer);
}
else
{
automationPeerList.AddRange(GetChildPeers(child));
}
}
}
return automationPeerList;
}
}
自定义数据网格
public class CustomDataGrid : DataGrid
{
//Override automation peer that the base class provides as it doesn't expose automation peers for the row details
protected override AutomationPeer OnCreateAutomationPeer()
{
return new GenericAutomationPeer(this);
}
}