在尝试了几种解决方案之后,我迫切需要帮助。
在最后复制之前,我尝试了几种方法,但仍然停留在使用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;
}
}
我既不能从GridPattern
获取TablePattern
实例,也不能从datagrid
获取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 Framework4.5。尝试了的常规用户权限和提升的管理权限,都得到了这里描述的相同的结果。
为什么DataGridView
返回0行?
为什么我不能得到其中一种模式?
你帮了我的忙!
更新:
詹姆斯·帮助并没有为我耍诡计。以下代码将返回所有行(包括标题):
var rows = dataGrid.FindAll(TreeScope.Children, PropertyCondition.TrueCondition);
标头单元随后可以由它们的ControlType
of ControlType.Header
识别。
发布于 2013-10-26 00:08:26
您正在复制的代码有缺陷。我只是在上面的代码中对这个示例程序保理进行了调整,测试了这个场景,它可以工作。
关键的区别在于,上面的代码使用TreeScope.Children
获取数据元素。此选项只获取父级的直接子级,因此如果数据集是嵌套的,它将无法工作。将其更改为使用TreeScope.Descendants
,它应该会像预期的那样工作。
var datagrid = bw.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "dgvControlProperties"));
这里有一个链接如何操作各种显像管选项。另外,我不知道如何将行绑定到网格,但我在测试场景中这样做了,它运行得非常完美。
希望这能帮上忙。
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;
发布于 2013-10-24 22:19:27
您的代码看起来很好,尽管这可能是一个焦点问题。
即使您正在获得对这些自动化元素对象的引用,在使用它们之前,也应该对它们设置焦点(使用恰当的命名为SetFocus方法)。
尝试:
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上,即
datagrid.SetFocus()
发布于 2013-11-05 01:22:44
为什么DataGridView返回0行?
DataGridViewRows有一个ControlType of ControlType.Custom。所以我修改了行文
// Find all rows from the DataGridView
var loginLines = datagrid.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.DataItem));
至
var loginLines = datagrid.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Custom));
这将使您获得DataGridView中的所有行。但是您的代码中有这个循环。
DataGridView (而不是DataGrid)支持什么模式?
LegacyIAccessiblePattern。试试这个-
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。
public class CommonDataGridView : System.Windows.Forms.DataGridView,
IRawElementProviderFragmentRoot,
IGridProvider,
ISelectionProvider
{.. }
完整的代码可以找到@ 此msdn链接。
一旦我这样做了,我就玩了一下visualUIVerify源代码。下面是如何访问gridview的单元格并更改值的方法。另外,注意注释的代码。我不需要那个。它允许您遍历行和单元格。
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;
}
希望这能帮上忙。
https://stackoverflow.com/questions/19511546
复制相似问题