首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >UI自动化不适用于DataGridView

UI自动化不适用于DataGridView
EN

Stack Overflow用户
提问于 2013-10-22 07:22:20
回答 4查看 9.7K关注 0票数 3

在尝试了几种解决方案之后,我迫切需要帮助。

在最后复制之前,我尝试了几种方法,但仍然停留在使用UIAutomation获取数据集的全部内容的解决方案上。

让我们谈谈代码,请考虑以下评论:

代码语言:javascript
运行
复制
// Get Process ID for desired window handle
uint processID = 0;
GetWindowThreadProcessId(hwnd, out processID);

var desktop = AutomationElement.RootElement;

// Find AutomationElement for the App's window
var bw = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ProcessIdProperty, (int)processID));

// Find the DataGridView in question
var datagrid = bw.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "dgvControlProperties"));

// Find all rows from the DataGridView
var loginLines = datagrid.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.DataItem));

// Badumm Tzzz: loginLines has 0 items, foreach is therefore not executed once 

foreach (AutomationElement loginLine in loginLines)
{
    var loginLinesDetails = loginLine.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Custom));

    for (var i = 0; i < loginLinesDetails.Count; i++)
    {
        var cacheRequest = new CacheRequest 
        { 
            AutomationElementMode = AutomationElementMode.None,
            TreeFilter = Automation.RawViewCondition
        };

        cacheRequest.Add(AutomationElement.NameProperty);
        cacheRequest.Add(AutomationElement.AutomationIdProperty);

        cacheRequest.Push();

        var targetText = loginLinesDetails[i].FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "TextBlock"));

        cacheRequest.Pop();

        var myString = targetText.Cached.Name;
    }

}

我既不能从GridPattern获取TablePattern实例,也不能从datagrid获取TablePattern实例,这都会导致异常:

代码语言:javascript
运行
复制
GridPattern gridPattern = null;

try
{
    gridPattern = datagrid.GetCurrentPattern(GridPattern.Pattern) as GridPattern;
}
catch (InvalidOperationException ex)
{
    // It fails!
}

TablePattern tablePattern = null;

try
{
    tablePattern = datagrid.GetCurrentPattern(TablePattern.Pattern) as TablePattern;
}
catch (InvalidOperationException ex)
{
    // It fails!
}

行预先添加到DataGridView中,如下所示:

代码语言:javascript
运行
复制
dgvControlProperties.Rows.Add(new object[] { false, "Some Text", "Some other text" });

我正在编译为.Net Framework4.5。尝试了的常规用户权限和提升的管理权限,都得到了这里描述的相同的结果。

为什么DataGridView返回0行?

为什么我不能得到其中一种模式?

你帮了我的忙!

更新:

詹姆斯·帮助并没有为我耍诡计。以下代码将返回所有行(包括标题):

代码语言:javascript
运行
复制
var rows = dataGrid.FindAll(TreeScope.Children, PropertyCondition.TrueCondition);

标头单元随后可以由它们的ControlType of ControlType.Header识别。

EN

回答 4

Stack Overflow用户

发布于 2013-10-26 00:08:26

您正在复制的代码有缺陷。我只是在上面的代码中对这个示例程序保理进行了调整,测试了这个场景,它可以工作。

关键的区别在于,上面的代码使用TreeScope.Children获取数据元素。此选项只获取父级的直接子级,因此如果数据集是嵌套的,它将无法工作。将其更改为使用TreeScope.Descendants,它应该会像预期的那样工作。

代码语言:javascript
运行
复制
var datagrid = bw.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "dgvControlProperties"));

这里有一个链接如何操作各种显像管选项。另外,我不知道如何将行绑定到网格,但我在测试场景中这样做了,它运行得非常完美。

希望这能帮上忙。

代码语言:javascript
运行
复制
public class DataObject
{
    public string FieldA { get; set; }
    public string FieldB { get; set; }
    public string FieldC { get; set; }
}

List<DataObject> items = new List<DataObject>();
items.Add(new DataObject() {FieldA="foobar",FieldB="foobar",FieldC="foobar"});
items.Add(new DataObject() { FieldA = "foobar", FieldB = "foobar", FieldC = "foobar" });
items.Add(new DataObject() { FieldA = "foobar", FieldB = "foobar", FieldC = "foobar" });

dg.ItemsSource = items;
票数 4
EN

Stack Overflow用户

发布于 2013-10-24 22:19:27

您的代码看起来很好,尽管这可能是一个焦点问题。

即使您正在获得对这些自动化元素对象的引用,在使用它们之前,也应该对它们设置焦点(使用恰当的命名为SetFocus方法)。

尝试:

代码语言:javascript
运行
复制
var desktop = AutomationElement.RootElement;

desktop.SetFocus();

// Find AutomationElement for the App's window
var bw = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ProcessIdProperty, (int)processID));

如果这不起作用,那么在调用“dataGrid”之前,尝试显式地将注意力集中在FindAll上,即

代码语言:javascript
运行
复制
datagrid.SetFocus()
票数 3
EN

Stack Overflow用户

发布于 2013-11-05 01:22:44

为什么DataGridView返回0行?

DataGridViewRows有一个ControlType of ControlType.Custom。所以我修改了行文

代码语言:javascript
运行
复制
// Find all rows from the DataGridView
var loginLines = datagrid.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.DataItem));

代码语言:javascript
运行
复制
var loginLines = datagrid.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Custom));

这将使您获得DataGridView中的所有行。但是您的代码中有这个循环。

DataGridView (而不是DataGrid)支持什么模式?

LegacyIAccessiblePattern。试试这个-

代码语言:javascript
运行
复制
 LegacyIAccessiblePattern legacyPattern = null;

       try
       {
           legacyPattern = datagrid.GetCurrentPattern(LegacyIAccessiblePattern.Pattern) as LegacyIAccessiblePattern;
       }
       catch (InvalidOperationException ex)
       {
           // It passes!
       }

正如我在@James上评论的那样,UIA不支持DataGridView (同样,不支持DataGrid)。

如果你在谷歌上搜索术语:"UI自动化DataGridView“,那么第一结果有一个不完整的答案。Mike回答了在源中创建什么提供者类(显然是扩展了DataGridView),不幸的是,我不知道如何使UIA加载该类的提供程序。如果有人能提供一些线索,菲尔和我会非常高兴的!

编辑

您的DataGridView应该在上面的链接中实现接口。一旦您这样做,行的ControlType将是ControlType.DataItem而不是ControlType.Custom。然后,您可以用它来使用DataGrid。

编辑

这就是我最后要做的-

创建如下所示的自定义DataGridView。您的datagridview也可以将其子类化。这将使它支持ValuePattern和SelectionItemPattern。

代码语言:javascript
运行
复制
public class CommonDataGridView : System.Windows.Forms.DataGridView,
    IRawElementProviderFragmentRoot,
    IGridProvider,
    ISelectionProvider
{.. }

完整的代码可以找到@ 此msdn链接

一旦我这样做了,我就玩了一下visualUIVerify源代码。下面是如何访问gridview的单元格并更改值的方法。另外,注意注释的代码。我不需要那个。它允许您遍历行和单元格。

代码语言:javascript
运行
复制
private void _automationElementTree_SelectedNodeChanged(object sender, EventArgs e)
    {
        //selected currentTestTypeRootNode has been changed so notify change to AutomationTests Control
        AutomationElementTreeNode selectedNode = _automationElementTree.SelectedNode;
        AutomationElement selectedElement = null;

        if (selectedNode != null)
        {
            selectedElement = selectedNode.AutomationElement;

            if (selectedElement.Current.ClassName.Equals("AutomatedDataGrid.CommonDataGridViewCell"))
            {
                if(selectedElement.Current.Name.Equals("Tej")) //Current Value
                {

                    var valuePattern = selectedElement.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;

                    valuePattern.SetValue("Jet");
                }



                //Useful ways to get patterns and values

                //System.Windows.Automation.SelectionItemPattern pattern = selectedElement.GetCurrentPattern(System.Windows.Automation.SelectionItemPattern.Pattern) as System.Windows.Automation.SelectionItemPattern;


                //var row = pattern.Current.SelectionContainer.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "AutomatedDataGrid.CommonDataGridViewRow", PropertyConditionFlags.IgnoreCase));

                //var cells = row.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "AutomatedDataGrid.CommonDataGridViewCell", PropertyConditionFlags.IgnoreCase));
                //foreach (AutomationElement cell in cells)
                //{
                //    Console.WriteLine("**** Printing Cell Value **** " + cell.Current.Name);

                //    if(cell.Current.Name.Equals("Tej")) //current name
                //    {

                //        var valuePattern = cell.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;

                //        valuePattern.SetValue("Suraj");
                //    }
                //}

                //Select Row
                //pattern.Select();

                //Get All Rows
                //var arrayOfRows = pattern.Current.SelectionContainer.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "AutomatedDataGrid.CommonDataGridViewRow", PropertyConditionFlags.IgnoreCase));


                //get cells
                //foreach (AutomationElement row in arrayOfRows)
                //{
                //   var cell = row.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "AutomatedDataGrid.CommonDataGridViewCell", PropertyConditionFlags.IgnoreCase));


                //    var gridItemPattern = cell.GetCurrentPattern(GridItemPattern.Pattern) as GridItemPattern;

                //    // Row number.
                //    Console.WriteLine("**** Printing Row Number **** " + gridItemPattern.Current.Row);

                //    //Cell Automation ID
                //    Console.WriteLine("**** Printing Cell AutomationID **** " + cell.Current.AutomationId);

                //    //Cell Class Name
                //    Console.WriteLine("**** Printing Cell ClassName **** " + cell.Current.ClassName);

                //    //Cell Name
                //    Console.WriteLine("**** Printing Cell AutomationID **** " + cell.Current.Name);                        
                //}

            }
        }

        _automationTests.SelectedElement = selectedElement;
        _automationElementPropertyGrid.AutomationElement = selectedElement;
    }

希望这能帮上忙。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19511546

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档