c# - UI 自动化不适用于 DataGridView

标签 c# winforms datagridview microsoft-ui-automation

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

我尝试了几种方法,在最终复制之前仍然坚持使用 Getting full contents of a Datagrid using UIAutomation 中的解决方案.

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

// 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;
    }

}

我既无法从 datagrid 获取 GridPattern 实例,也无法获取 TablePattern 实例,两者都会导致异常:

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,如下所示:

dgvControlProperties.Rows.Add(new object[] { false, "Some Text", "Some other text" });

我正在编译为 .Net Framework 4.5。尝试了 UI Automation 客户端的常规用户权限和提升的管理员权限,两者都产生了此处描述的相同结果。

为什么 DataGridView 返回 0 行?

为什么我无法获得其中一种模式?

感谢您帮助我!


更新:

James 的帮助对我没用。以下代码会返回所有行(包括标题):

var rows = dataGrid.FindAll(TreeScope.Children, PropertyCondition.TrueCondition);

然后可以通过 ControlType.HeaderControlType 来识别标题单元格。

最佳答案

您复制的代码有缺陷。我刚刚用 this sample program 的改编测试了这个场景考虑到您上面的代码,它可以工作。

主要区别在于上面的代码使用 TreeScope.Children 来获取数据网格元素。此选项仅抓取父项的直接子项,因此如果您的数据网格是嵌套的,它将无法工作。将其更改为使用 TreeScope.Descendants,它应该会按预期工作。

var datagrid = bw.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "dgvControlProperties"));

Here is a link了解各种 Treescope 选项的行为方式。另外,我不知道你是如何将行绑定(bind)到网格的,但我在我的测试场景中是这样做的,而且它工作得很好。

希望这对您有所帮助。

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;

关于c# - UI 自动化不适用于 DataGridView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19511546/

相关文章:

c# - 从文本框帮助更新 Access 数据库时出现问题?

c# - 请向我解释这个 BackgroundWorker 事件

c# - 以前的工具提示保留在鼠标移动时,不刷新!

c# - 当设置了 DefaultCellStyle.Format 且数据为空时显示空单元格

c# - 在多列上对 DataGridView 进行排序?

c# - 将数据从行保存到数据库

c# - 带参数登录 asp.net 重定向

c# - 在 C# 中重用或处理自定义字体的有效方法

c# - 使用 DisplayField-ValueField 项目填充组合框 与我们在 asp.net 中所做的类似

c# - Task.Delay() 未按预期运行