How do I invoke a TreeNode context menu when it scrolls off screen ?

Jan 12, 2011 at 3:01 PM
Edited Jan 12, 2011 at 3:02 PM

I'm trying to write a stress test (WPF App running on Win7). Assume that a tree node has a right click 'Add child' menu option. So my test is basically adding ~1000 children in a loop.


TreeNode parentNode = GetNode(parentNodePath);

var pointToClick = parentNode.Location;
            // sometimes win7 themes and layout can cause the treenode clickable area
            // to shift slightly towards the right by a few pixels causing White to miss!

var menu = _mainWindow.Popup.Item("Add");


However I find that the following code works for the first 2 iterations. On the third iteration, the parent is off-screen. The tree has scrolled down due to the sub-trees of the new child nodes. Now the Menu option click doesn't work anymore although there seems to be some scrolling into view that happens automatically.

Next I tried the following ways to get around this:

  • _tree.ScrollBars.Vertical.ScrollUp()
  • using the  approach Throndorin details here i.e. using the ScrollItemPattern and ScrollIntoView()

I couldn't get it to work. So any help would be appreciated

Some supporting questions :

What does the IsOffScreen property do ? What do I use to check if a particular element has scrolled out of view ?

I also saw a WPFTreeNode class - should I be using it ?

Here is the snipped LogStructure output if it helps. Each TreeNode contains an Icon + Text. Also when a new node is added, the content is replaced by an editable textbox so that the node can be renamed (using DataTemplates)


Thanks for reading...


Jan 13, 2011 at 6:28 AM



scrolling in Tree has some problems:

- in UIAutomation is a problem if a TreeNode is selected (not the root)

- Lazy Loading (not all Treenodes are loaded if Tree is deep, only visible Nodes are loaded)



treeNode.GetItem("root node", "subnode", "subsubnode").

=> these operation will automatically expand tree if needed and try to bring nodes in View, but fails on deep trees because of lazy loading


IsOffscreen Property: is true if an element is not visible in view.



some ideas to make it work:


- collapse Tree complete before start)

- collapse node if all subnodes are verified

- maximize TreeView if possible

- remove TreeNodes from selection (handles UIAutomation scrolling bug)

- use keybaord handling (SpecialKey.DOWN) to step to next Node (that should bring nodes into view)

- use Thread.Sleep to have short breaks (make stable your test)








Jan 18, 2011 at 8:38 AM

Hi Throndorin - I apologize for the delay in responding -- had a long weekend :)

First step : Figure out if scrolling is required

Here I have a problem.


TreeNode parentNode = _treeHandle.Node(nodePath.Split('\\'))

var aeClickPoint = parentNode.AutomationElement.GetClickablePoint();
Console.Out.WriteLine("Visible={0}, IsOffScreen={1}, Location={2},{3} AEClickPoint={4},{5}",
                parentNode.Location.X, parentNode.Location.Y,
                aeClickPoint.X, aeClickPoint.Y);

Here is the sample output

Visible=True, IsOffScreen=False, Location=9,215 AEClickPoint=187,354
Added Animal #0

Visible=True, IsOffScreen=False, Location=9,215 AEClickPoint=185,760
Added Animal #1

Visible=True, IsOffScreen=False, Location=9,215 AEClickPoint=10,216

Once the second node is added, the parent has scrolled offscreen. As you can see that there is some caching happening (seen from the AutomationElement.GetClickPoint output) - the TreeNode properties seem to be frozen (returning the same values irrespective of the current position of the node). How do I get white to get me the latest property value - something that relates to visible position?

Second Step : Scroll so as to center the parent node on screen

Here I have a bunch of questions :)

  • How do I deselect a node using White ? To get around the bug that you mentioned. I tried cache selection=>select root=> scroll => reset to cached selection. Here I find the scroll actually works, but any attempt to click / right click on the node sets the scrollbar to an arbitrary position (the node is now off screen again). Now that I debug it, I see that just calling _treeHandle.Node() causes the node to scroll into view. But the next thing that I do - treeNode.RightClickAt(point) causes the scrollbar to jump as before.
  • All nodes that I am right clicking on are expanded / visible - so not sure if I should worry about the lazy loading.
  • I already have a Sleep in my loop - but it isn't helping.

Trying the keyboard down key tip & see if that solves my problem. I've a feeling that I am missing something quite basic here..



Jan 18, 2011 at 9:02 AM

Some more information on the scrollbar jump when you click/right click the tree node.

watch expression: ((White.Core.UIItems.Scrolling.WPFVScrollBar)(_treeHandle.ScrollBars.Vertical))

ScrollPercentage=39.38, Value = 31.81

Step: execute _treeHandle.Node(parentNodePath) for the root node

ScrollPercentage=39.38, Value = 0

Step: parentNodePath.RightClickAt(point)

ScrollPercentage=39.38, Value = 64.97

Jan 18, 2011 at 9:34 AM



Microsoft says, the problem is eventing, if a TreweNode is selected, the TreeControl try's to scroll back to the selected Element.

This is a bug, Workaround is: Deselect the treeNode.

you can't deselect using White, you should use SelectionItemPattern


/// <summary>
/// Gets the specified pattern.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="value">The value.</param>
/// <returns></returns>
public static AutomationPattern GetSpecifiedPattern(AutomationElement element, string value)
  AutomationPattern[] supportedPattern = element.GetSupportedPatterns();

  AutomationPattern automationValuePattern = null;
  foreach (AutomationPattern pattern in supportedPattern)
	if (pattern.ProgrammaticName == value)
	  automationValuePattern = pattern;
  return automationValuePattern;

/// <summary>
/// Removes from selection.
/// </summary>
/// <param name="automationElement">The automation element.</param>
public static void RemoveFromSelection( AutomationElement automationElement )
  AutomationPattern automationPatternFromElement = GetSpecifiedPattern(automationElement, "SelectionItemPatternIdentifiers.Pattern");

  if (automationPatternFromElement != null)
	SelectionItemPattern selectionPattern = (SelectionItemPattern)automationElement.GetCurrentPattern(automationPatternFromElement);

To find out lazy loading or something like that is activated, open a treeNode with much more elements as the view can show and call on parent Node

int count = node.Nodes.Count;


are the numer of nodes correct ?


Getting TreeNodes:


if I want to verify a TreeNode I always use the complete path to get it.

- So I move the tree to the top before trying to verify the next node (or I verify node.Nodes.)

- if the tree is expanded I collapsed all elements

But the best way:

If I have the option to verify the tree if there are not to much nodes I verify here and not if the tree has many nodes. And I f you can give the tree more width and hight I use:

 if (window.DisplayState != DisplayState.Maximized)
    window.DisplayState = DisplayState.Maximized;

if possible.