Reputation: 3758
I am trying to select a tree item in a Coded UI Test, but I don't know the entire hierarchy.
Example:
- mssql connection
- Tables
- Unknown
- FirstName
Is there a way to search for this FirstName tree item and specify that it is so many levels deep, without specifying the entire path?
It doesn't look like any of the Search Configuration properties will do this.
Upvotes: 2
Views: 1007
Reputation: 1017
public static UITestControl GetTreeItem(UITestControl TreeControl, string ItemName, bool ContainsTrue = true)
{
AutomationElement tree = AutomationElement.FromHandle(TreeControl.WindowHandle);
System.Windows.Automation.ControlType controlType = tree.Current.ControlType;
//Get collection of tree nodes.
AutomationElementCollection treeNodeCollection = null;
treeNodeCollection = tree.FindAll(TreeScope.Descendants,
new System.Windows.Automation.PropertyCondition(AutomationElement.ControlTypeProperty,
System.Windows.Automation.ControlType.TreeItem));
UITestControl ReqTreeItem = new UITestControl();
foreach (AutomationElement item in treeNodeCollection)
{
if ((item.Current.Name == ItemName) && (!ContainsTrue))
{
ReqTreeItem = UITestControlFactory.FromNativeElement(item, "UIA");
break;
}
if ((item.Current.Name.Contains(ItemName)) && (ContainsTrue))
{
ReqTreeItem = UITestControlFactory.FromNativeElement(item, "UIA");
break;
}
}
return ReqTreeItem;
}
Upvotes: 1
Reputation: 676
When your control was mapped in the UI map, perhaps the full hierarchy was used, eg
mssql connection -Tables --Unknown1 ---FirstName
resulted in 4 mapped controls.
You can edit the uimap .xml file manually carefully removing the -Unknown1 element, and making sure that MatchExactHierarchy is turned off. That way the search will originally fail, move on to using heuristics to look for elements deeper in the tree than the immediate children and should find your control.
Upvotes: 0
Reputation: 2243
If FirstName is unique in the tree, then you can use PInvoke, and you won't need to specify the depth:
public static List<IntPtr> GetChildWindows(IntPtr parent)
{
var result = new List<IntPtr>();
var listHandle = GCHandle.Alloc(result);
try
{
var childProc = new User32.EnumWindowsProc(EnumWindow);
User32.EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
var gch = GCHandle.FromIntPtr(pointer);
var list = gch.Target as List<IntPtr>;
if (list == null)
{
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
// Modify this to check to see if you want to cancel the operation, then return a null here
return true;
}
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr window, EnumWindowsProc callback, IntPtr i);
// sample usage:
public void findWindowUser32()
{
foreach (IntPtr child in GetChildWindows(User32.FindWindow(null, "Untitled - Notepad")))
{
StringBuilder sb = new StringBuilder(100);
User32.GetClassName(child, sb, sb.Capacity);
if (sb.ToString() == "Edit")
{
uint wparam = 0 << 29 | 0;
User32.PostMessage(child, WindowsConstants.WM_KEYDOWN, (IntPtr)Keys.H, (IntPtr)wparam);
}
}
}
Upvotes: 1