Custom WPFListView control

Jan 22, 2010 at 2:12 AM

Hi, I am trying to read values from a WPFListView which has some (not all) custom columns.

To get the information about the columns of this list view I iterate over <ListView Object>.Header.Columns and able to get all column names.

When I try to iterate over each cell (in each row) I can get handle of conventional cells only. Even in VS2008 debugger I don't see any Cell/Object/or anything else for custom cells in that row. Any pointers?

 

Thanks,

-Parth

Coordinator
Jan 28, 2010 at 4:15 PM

Look at the section on WPFItems here: http://white.codeplex.com/wikipage?title=UI%20Items&referringTitle=Home

Jan 28, 2010 at 5:20 PM

Thanks for the pointer Vivek. I already did look at it prior to posting this message.

In my case, WPFDataGrid (List View in WHITE) has few columns. All columns are tied with the data.

  • Non custom columns have Header, Name (x:Name) and DisplayMemberBinding properties assigned in xaml
  • Custom columns have only TextBlock property assigned inside CellTemplate on GridViewColumn in xaml. This is the place where I am not able to get handle.

I have also tried iterating over cells in each row, but rows doesn't even show an object for cell for custom columns. Is there any alternative idea I can try?

Jan 29, 2010 at 9:04 AM

Hi I have had the same problem,

 

the problem ist that the rows does not contains cells as in WinForm UI's

 

I wrote a class to handle our WPF Grid

 

here the custom control for the grid cell

 

using System;
using System.Text.RegularExpressions;
using System.Windows.Automation;
using NUnit.Framework;
using White.Core.UIItems;
using White.Core.UIItems.Actions;
using White.Core.UIItems.Custom;
using White.Core.UIItems.Finders;
using White.Core.UIItems.ListBoxItems;
using White.Core.UIItems.WPFUIItems;

namespace TestHelper.CustomUIItems
{
  /// <summary>
  /// class to handle the custom UI Item "ListViewCell" in  Grids
  /// </summary>
  [ControlTypeMapping(CustomUIItemType.Custom)]
  public class MyListViewCell : CustomUIItem
  {

    // Implement these two constructors. The order of parameters should be same.
    /// <summary>
    /// Initializes a new instance of the <see cref="MyListViewCell"/> class.
    /// </summary>
    /// <param name="automationElement">The automation element.</param>
    /// <param name="actionListener">The action listener.</param>
    public MyListViewCell(AutomationElement automationElement, ActionListener actionListener)
      : base(automationElement, actionListener) {}

    //Empty constructor is mandatory with protected or public access modifier.
    /// <summary>
    /// Initializes a new instance of the <see cref="MyListViewCell"/> class.
    /// </summary>
    protected MyListViewCell() {}

    /// <summary>
    /// Gets the text.
    /// </summary>
    /// <returns></returns>
    public string GetText()
    {
      try
      {
        Label box = (Label)this.Get(SearchCriteria.ByControlType(ControlType.Text));
        if(box == null)
        {
          ComboBox combobox = this.Get<ComboBox>( SearchCriteria.ByControlType( ControlType.ComboBox ) );
          return combobox.SelectedItemText;
        }

        return box.Name;
        
      }
      catch (System.Exception)
      {
        return null;
      }
    }

    /// <summary>
    /// Gets the index.
    /// </summary>
    /// <returns></returns>
    public int GetIndex()
    {
      string name = Name;
     
      string regex = @"(?<string>.*:\s)(?<index>[0-9]*)";
      Regex ex = new Regex( regex );
      if(ex.IsMatch(name))
      {
        return Convert.ToInt32(ex.Match( name ).Groups["index"].Value);
      }
      return -1;
    }

    /// <summary>
    /// Gets the edit field of the Cell.
    /// </summary>
    /// <returns>the edit field if exists, null otherwise</returns>
    /// <exception cref="AssertionException">Throws AssertionException if element is not visible</exception>
    public TextBox GetEditField()
    {
      AutomationElement element = automationElement.FindFirst( TreeScope.Children, new PropertyCondition( AutomationElement.ControlTypeProperty, ControlType.Edit ) );
      TextBox edit = new TextBox( element, ActionListener );//this.Get<TextBox>( SearchCriteria.ByControlType( ControlType.Edit ) );
      Assert.IsFalse(edit.IsOffScreen);
      return edit;
    }

  }
}

 

Feb 4, 2010 at 7:11 PM

Thanks Thondroin.

Can you please also show some code about how to handle this in ListView (Grid)? I mean how to get handle of this custom cell instead of standard cell? I have been trying Get<CustomCell> without any success.

Feb 5, 2010 at 8:56 AM

Hi

 

this is a not so nice way but I have problems getting custom controls using the Get or GetMultiple on UIItems (I hope this will be fixed in later releases of White)

so I come back to Automation element

 

foreach (ListViewRow row in _rows)
{
// scroll the automation element in the view there is no good way in white in the moment :(
AutomationElementHelper.ScrollAutomationElement(row.AutomationElement);

PropertyCondition propertyClassName = new PropertyCondition(AutomationElement.ClassNameProperty, "DataGridCell");
PropertyCondition propertyConditionControlType = new PropertyCondition(AutomationElement.ControlTypeProperty,
ControlType.Custom);
//the count of cells cannot be correct performed, if many cells are displayed AutomationElementCollection itemCollection = row.AutomationElement.FindAll(TreeScope.Descendants, new AndCondition( propertyClassName, propertyConditionControlType));
List<MyListViewCell> cells = new List<MyListViewCell>();


// add all cells to the List as ETS4ListViewCell foreach (AutomationElement element in itemCollection)
{
cells.Add( new MyListViewCell( element, _listView.ActionListener ) );
}

 

 

 

as you can see I use the constructor of MyListViewCell, the ActionListener is the same as each UIItem of your application has.

I'm not sure but each cell automationID contains the index by default, but you should not use this because it contains the namespace of the element and the name and if this changes you have to change your code too.

So as you can see I use a Regular expression to get only the index and ignore the rest. (look at MyListViewCell.GetIndex() )

 

 

Throndorin

 

May 12, 2010 at 2:38 AM
Edited May 12, 2010 at 2:39 AM

HI Throndorin,

I am also facing similar issue as mentioned in this thread. I would like to know the namespace which can give me AutomationElementHelper as i was unable to locate the same. Awaiting reply.

May 12, 2010 at 7:13 AM
rickrocksworld wrote:

HI Throndorin,

I am also facing similar issue as mentioned in this thread. I would like to know the namespace which can give me AutomationElementHelper as i was unable to locate the same. Awaiting reply.

Hi rickrocksworld,

 

this helper class is our own work :), but I can send to you if you send me your mail address.

 

here you can see what the function above do:

 

/// <summary>
/// Gets the specified pattern.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="value">The value.</param>
/// <returns></returns>
private 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;
	  break;
	}
  }
  return automationValuePattern;
}


/// <summary>
/// Scroll the automation element
/// </summary>
/// <param name="element">The element.</param>
public static void ScrollAutomationElement(AutomationElement element)
{
  AutomationPattern automationPatternFromElement = GetSpecifiedPattern(element, "ScrollItemPatternIdentifiers.Pattern");

  if (automationPatternFromElement != null)
  {
	ScrollItemPattern scrollPattern = (ScrollItemPattern)element.GetCurrentPattern(automationPatternFromElement);
	scrollPattern.ScrollIntoView();
  }
}

 

Throndorin

May 12, 2010 at 7:16 PM

Hey Throndorin,

My mail id is rickrocksworld@gmail.com. If you could send on this mail id it would be of great help.

Thanks a lot for the reply and awaiting your mail.

May 17, 2010 at 8:37 AM

Hi

I'm now on vacation, will send the file, after 24.05

 

Throndorin

 

May 18, 2010 at 2:27 AM
Edited May 18, 2010 at 2:30 AM

Hi Throndorin

I tried to apply your solution but the list view which we have has four custom nodes and I'm not able to get handle of any of the list view items with your solution too.

I used UISpy and i got four custom nodes for the listview containing different items. The first node contains only image. The second node contains image and text. The third node has text and fourth too. I want to get hold of the second node.

While debugging the listView shows that there are rows but going inside these rows i don't get any cells. So even when I apply your solution it doesn't return me any cells or rather element collection. Any pointers for the problem.

 

Thanks

rickrocksworld

Coordinator
May 18, 2010 at 6:26 AM

what does UISpy show?