views:

301

answers:

2

Note: This is no longer an issue, the .NET 4 built-in DataGrid solves this problem


I have a WPF app which is using a DataGrid; I'm using the WPF ui automation API to write some automated tests for it. The DataGrid is the WPFToolkit one, I'm using the .NET 3.5SP1 with VS2008, and, the datagrid has multi-select enabled.

Where I'm at is that from my test can find the datagrid, and I can find individual cells within the grid using the GridPattern.GetItem method, and select them by setting SelectionItemPattern.Select. Method

The code looks somewhat like this:

AutomationElement mainGrid = // find the grid in the window
var columnCount = (int)mainGrid.GetCurrentPropertyValue(GridPattern.ColumnCountProperty);
var mainGridPattern = (GridPattern)mainGrid.GetCurrentPattern(GridPattern.Pattern);

var rowToSelect = 2;

// select just the first cell
var item = mainGridPattern.GetItem(rowToSelect, 0);
var itemPattern = (SelectionItemPattern)item.GetCurrentPattern(SelectionItemPattern.Pattern);
itemPattern.Select();

This seems to work, but it only selects the first individual cell, not the entire table row (which has 10 columns) but I can't work out how to deselect an item. The only thing I can find that looks like it might work is to call SelectionItemPattern.AddToSelection() on the itemPattern, or the corresponding RemoveFromSelection but when I do either of these, the following exception is raised:

=> Cannot change cell selection when the SelectionUnit is FullRow.
   at MS.Internal.Automation.ElementUtil.Invoke(AutomationPeer peer, DispatcherOperationCallback work, Object arg)
   at MS.Internal.Automation.SelectionItemProviderWrapper.AddToSelection()

The underlying root issue appears to be that (as far as I can see) the WPF UI automation API has no concept of a grid Row, only cells. This seems somewhat problematic - Is this right?

Sidenote: I had previously been using the White UI automation framework - this doesn't use UI automation to select grid rows, instead it moves the mouse to the row location and clicks it - which caused random failures of our tests - is this why they're using the mouse to do the selection though?

A: 

If you use UISpy to look at the structure of your DataGrid as UIAutomation sees it, you'll notice that the DataGrid element contains a RowsPresenter, and the RowsPresenter contains a number of DataGridRows, each containing a DataGridCell.

I suspect what's happening is that var item = mainGridPattern.GetItem(rowToSelect, 0); is returning the item representing the cell, whereas you want the item representing the whole row.

You can get this by calling item.CachedParent - then Select() that.

Samuel Jack
I'd noticed this, but there are two problems: - the RowsPresenter is an implementation detail of the toolkit datagrid (as opposed to a core property/pattern) - and, there is no pattern to get the RowsPresenter :-(
Orion Edwards
FYI: `mainGrid.GetItem(0,0)` returns a UIElement representing the cell. `cell.CachedParent` throws an exception: `TypeError: Cannot request a property or pattern that is not cached.`
Orion Edwards
A: 

This now seems to have been fixed in .NET 4. Rows are now exposed as real objects that support the SelectionItemPattern, so you can now select/deselect a row. Hooray

Orion Edwards