Unable to identify the value of cells inside the WPF Datagrid

Jun 8, 2012 at 2:01 PM
Edited Jun 11, 2012 at 6:50 AM

Hi,

I am having a wpf datagrid.
It's hierarchy in uispy is:-

-Datagrid(AutomationID:-mainGrid)

         - pane(header panel)

         -pane(Data panel)

                 - Dataitem "Row 0"

                          -"Custom" Item

                          -"Custom"

         -pane(Footer panel)

 

So, all the rows and columns are inside the Data panel pane as shown above.

I am only able to identify the RowCount and ColumnCount of the datagrid but not able to identify the rows/columns or cells of the grid.

I am using the below code:-

  AutomationElement elem = win.Get(SearchCriteria.ByNativeProperty(AutomationElement.AutomationIdProperty,"mainGrid")).AutomationElement;
  GridPattern grid = (GridPattern)elem.GetCurrentPattern(GridPattern.Pattern);

Till the above statement everything works fine and the GridPattern is identified.

But the below statement returns nothing.

GridItemPattern grids = (GridItemPattern)elem.GetCurrentPattern((AutomationPattern) GridItemPattern.ContainingGridProperty);

I have tried hell lot of things but everything was in vain.

I have wasted 3 full days in identifying it. But, nothing helped.

If anyone has some idea then please suggest. We are in a crucial stage of the project.

Also, I am aware that few discussions have already been happened related to datagrid. I have gone through them as well and tried implementing but it didnt work. That is why I have raised a new thread.

Looking forward to someone's response ASAP.

Jun 11, 2012 at 5:58 PM

I spent a lot of time getting both WPF Datagrids and WPF ListViews to work with White and Windows Automation. Here is a sample of what I did, it works well, let me know if you want any more examples...

Here are 2 main functions I use where oGrid is the WPF datagrid already found with White. The DataGridCell and DataGridChildControl classes are simple and their members should be apparent from these examples, but let me know if you want more info.

//finding an individual cell in a grid and returning its index and bounds
        public DataGridCell GetCell(int iRow, int iCol)
        {
            DataGridCell gGridCell = new DataGridCell();
            int iColumnCount = Columns;

            //set up property condition to be catch all datagrid cells
            gGridCell.cellCondition = new PropertyCondition(AutomationElement.IsGridItemPatternAvailableProperty, true);

            //find the correct Automation Element
            gGridCell.cellIndex = ((iRow) * iColumnCount) + iCol;
            gGridCell.automationElement = oGrid.AutomationElement.FindAll(TreeScope.Descendants, gGridCell.cellCondition)[gGridCell.cellIndex];

            //set the Bounds of the Cell
            gGridCell.top = oGrid.AutomationElement.FindAll(TreeScope.Descendants, gGridCell.cellCondition)[gGridCell.cellIndex].Current.BoundingRectangle.Top;
            gGridCell.left = oGrid.AutomationElement.FindAll(TreeScope.Descendants, gGridCell.cellCondition)[gGridCell.cellIndex].Current.BoundingRectangle.Left;
            gGridCell.width = oGrid.AutomationElement.FindAll(TreeScope.Descendants, gGridCell.cellCondition)[gGridCell.cellIndex].Current.BoundingRectangle.Width;
            gGridCell.height = oGrid.AutomationElement.FindAll(TreeScope.Descendants, gGridCell.cellCondition)[gGridCell.cellIndex].Current.BoundingRectangle.Height;

            return gGridCell;
        }

        public UIItem GetControl(int iRow, Object iCol, rnControlTypes cControlType, int controlIndex = 0)
        {
            if (iCol.GetType().Name == "String") iCol = GetColumnIndex(iCol.ToString());

            DataGridChildControl gControl = new DataGridChildControl();
            int iColumnCount = Columns;

            //set up property condition to be catch all datagrid cells
            gControl.cellCondition = new PropertyCondition(AutomationElement.IsGridItemPatternAvailableProperty, true);

            //now define the condition of the control type you are looking for that is contained in the cell
            gControl.controlCondition = ControlManager.GetTypePropertyCondition(cControlType);

            //find the correct Automation Element
            gControl.controlIndex = ((iRow) * iColumnCount) + Convert.ToInt32(iCol);

            White.Core.UIItems.UIItem control;

            switch (cControlType)
            {
                case rnControlTypes.rnButton:
                    control = new Button(oGrid.AutomationElement.FindAll(TreeScope.Descendants, gControl.cellCondition)[gControl.controlIndex].FindAll(TreeScope.Descendants, gControl.controlCondition)[controlIndex], base.window);
                    break;
                case rnControlTypes.rnCheckbox:
                    control = new CheckBox(oGrid.AutomationElement.FindAll(TreeScope.Descendants, gControl.cellCondition)[gControl.controlIndex].FindAll(TreeScope.Descendants, gControl.controlCondition)[controlIndex], base.window);
                    break;
                case rnControlTypes.rnCombobox:                   
                    control = new White.Core.UIItems.ListBoxItems.ComboBox(oGrid.AutomationElement.FindAll(TreeScope.Descendants, gControl.cellCondition)[gControl.controlIndex].FindAll(TreeScope.Descendants, gControl.controlCondition)[controlIndex], base.window);
                    control.Click();
                    control.Click();
                    break;
                case rnControlTypes.rnEditbox:
                    control = new TextBox(oGrid.AutomationElement.FindAll(TreeScope.Descendants, gControl.cellCondition)[gControl.controlIndex].FindAll(TreeScope.Descendants, gControl.controlCondition)[controlIndex], base.window);
                    break;
                case rnControlTypes.rnTextbox:
                    control = new TextBox(oGrid.AutomationElement.FindAll(TreeScope.Descendants, gControl.cellCondition)[gControl.controlIndex].FindAll(TreeScope.Descendants, gControl.controlCondition)[controlIndex], base.window);
                    break;
                case rnControlTypes.rnHyperlink:
                    control = new Hyperlink(oGrid.AutomationElement.FindAll(TreeScope.Descendants, gControl.cellCondition)[gControl.controlIndex].FindAll(TreeScope.Descendants, gControl.controlCondition)[controlIndex], base.window);
                    break;
                default:                   
                    control = new TextBox(oGrid.AutomationElement.FindAll(TreeScope.Descendants, gControl.cellCondition)[gControl.controlIndex].FindAll(TreeScope.Descendants, gControl.controlCondition)[controlIndex], base.window);
                    break;
            }

            return control;
        }

Jun 12, 2012 at 11:04 AM
Edited Jun 12, 2012 at 11:14 AM

Thanks wwarwood for the response.

I am trying to integrate your code to the existing code of mine.

I am unable to get the cellcondition property for the DataGridCell. Any idea? Any special assembly reference is required for it?

Thanks.

Jun 12, 2012 at 4:55 PM

Sure, it is just a condition:

Condition cellCondition = new PropertyCondition(AutomationElement.IsGridItemPatternAvailableProperty, true);

 

 

 

 

 

 

In your using statements you need: using System.Windows.Automation;

Jun 12, 2012 at 4:56 PM

It is also nice to note that the same properties and conditions for the WPF ListView control work almost EXACTLY like the data grid. I hardly had to change anything.

Oct 17, 2012 at 8:11 AM
Edited Oct 17, 2012 at 8:20 AM

Hey wwarwood  Can you please give some example with with ListView ? 

I am finding some difficulties finding a cell in listview.

And How can you get listviewcell.top etc properties ?

Oct 17, 2012 at 8:13 AM
Edited Oct 17, 2012 at 9:01 AM

Hi wwarwood,

I am trying to use your code to access grid. I am unable to get gGridCell.cellIndex, gGridCell.top and other methods related to gGridCell.

I am also not able to get DataGridChildControl reference.

Can you please share what are all the dll files required to run the code.

I think my question is similar to the one prasadkhare is asking.

Thanks.