mejdev
mejdev

Reputation: 3758

Searching for tree item when I don't know exact tree hierarchy

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

Answers (3)

KR Akhil
KR Akhil

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

Stas Sh
Stas Sh

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

chrismead
chrismead

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

Related Questions