我的asp.net页面上有一个托管Silverlight xap的对象(在我的特殊情况下,它在IFrame中,但我对常规对象也很好奇)。我可以在UI Spy中找到该元素,但名称只是“Silverlight Control”。试图在我的自动化测试中发现AutomationElement不成功(每次控制为空)。 Silverlight代码或html中是否有设置可以提供帮助?如果同一页面上有多个Silverlight控件,我该如何区分它?
<object id="silverlightClient" style="display:none;" data="data:application/x-silverlight-2," type="application/x-silverlight-2">
<param name="source" value="../../ClientBin/SilverlightApplication.xap"/>
<param name="onerror" value="onSilverlightError" />
<param name="background" value="#00000000" />
<param name="minRuntimeVersion" value="4.0.41019.0" />
<param name="autoUpgrade" value="true" />
<param name="windowless" value="false" />
</object>
TreeWalker tw = new TreeWalker(new System.Windows.Automation.PropertyCondition(AutomationElement.NameProperty, "Silverlight Control));
AutomationElement control = tw.GetFirstChild(ancestor);
UI间谍
Identification
ClassName: "MicrosoftSilverlight"
ControlType: "ControlType.Window"
Culture: "(null)"
AutomationId: "71857844"
LocalizedControlType: "window"
Name: "Silverlight Control"
ProcessId: "7636 (iexplore)"
RuntimeId: "42 2163886"
IsPassword: "False"
IsControlElement: "True"
IsContentElement: "True"
编辑:添加了图片,我也意识到该对象位于IFrame内部。 UISpyImage - title name removed
答案 0 :(得分:0)
我已经创建了一些扩展方法,以便更轻松地使用AutomationElement。我已粘贴下面的相关内容,但您可以详细了解它们here。
我假设您已经获得了根IE窗口的引用。如果没有,但你知道它是进程ID,你可以这样找到它:
var ieWindow = AutomationElement.RootElement.FindChildByCondition(new PropertyCondition(AutomationElement.ProcessIdProperty, ieProcessId));
假设在IE中只打开一个Frame,并在其上打开一个Silverlight控件,则可以执行以下操作:
var silverlightControl = ieWindow.FindDescendentByClassPath(
new[]{
"Frame Tab",
"TabWindowClass",
"Shell DocObject View",
"Internet Explorer_Server",
"MicrosoftSilverlight",
});
如果您有多个Silverlight控件,我不知道通过UIAutomation区分它们的方法。我会尝试从上面的类路径中删除“MicrosoftSilverlight”条目,以便您获得对Explorer页面的引用。然后使用
AutomationElement.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "MicrosoftSilverlight"))
找到所有的SilverlightControls,然后探测它们,然后在它们中找到一些允许你区分它们的元素。
以下是扩展方法:
public static class AutomationExtensions
{
public static AutomationElement FindDescendentByClassPath(this AutomationElement element, IEnumerable<string> classNames)
{
var conditionPath = CreateClassNameConditionPath(classNames);
return element.FindDescendentByConditionPath(conditionPath);
}
public static AutomationElement FindDescendentByConditionPath(this AutomationElement element, IEnumerable<Condition> conditionPath)
{
if (!conditionPath.Any())
{
return element;
}
var result = conditionPath.Aggregate(
element,
(parentElement, nextCondition) => parentElement == null
? null
: parentElement.FindChildByCondition(nextCondition));
return result;
}
public static AutomationElement FindChildByCondition(this AutomationElement element, Condition condition)
{
var result = element.FindFirst(
TreeScope.Children,
condition);
return result;
}
public static IEnumerable<Condition> CreateClassNameConditionPath(IEnumerable<string> classNames)
{
return classNames.Select(name => new PropertyCondition(AutomationElement.ClassNameProperty, name, PropertyConditionFlags.IgnoreCase)).ToArray();
}
}