问题描述
在这种情况下,我们有一个包含DataGrid的页面,现在我们要从此DataGrid中获取所有数据,但不访问其基础项源,即我们想直接访问该数据从DataGrid。这似乎很棘手,但并非不可能。我找到了很多类似这样的文章: ,并且:,还有许多其他。它们基本上是相同的:在另一个GetVisualChild函数的帮助下在DataGrid上定义扩展方法以查找目标DataGridCell对象。但是,当我使用它时,找不到目标单元格。具体而言,DataGrid中的每一行对应于DataContext集合中的一项,也就是说,它是类型为 Employee的集合,并且DataGrid的每一列都对应于Employee类的一个属性,例如Name,Gender ,年龄。现在我的问题是,上面提到的GetCell()函数总是以其一个内容(即DataGridCell中Content的属性)找到一个以Employee对象为对象的DataGridCell,无论我给哪个列索引,都无法深入研究每个属性它。
例如,在GetCell函数中,只有一行:
Dim单元格为DataGridCell = DirectCast(presenter.ItemContainerGenerator.ContainerFromIndex(column),DataGridCell)
,
,其中演示者是我所代表的DataGridCellsPresenter,它代表我选择的行,并且一旦我给出了列索引,我自然希望它返回指定位置上所选属性的控件。但是它并没有按预期工作。任何帮助将不胜感激!
We have such a scenario that we have a page including a DataGrid, and now we want to get all data from this DataGrid, but without accessing to the underlying item source of it, i.e., we want to access to the data directly from the DataGrid. It seems to be tricky but not impossible. I found many articles, like this: DataGridHelper, and this: Get WPF DataGrid row and cell, and many other ones. They are basically the same thing: to define the extension methods on DataGrid with help of another GetVisualChild function to find the target DataGridCell object. However, when I am using it, I can't find the target cell. Specifically, Each row in the DataGrid corresponds to one item from a collection of the DataContext, let's say, it is a collection of type "Employee", and each column of the DataGrid corresponds one property of class Employee, e.g, the Name, Gender, Age. Now my problem is, the above-mentioned GetCell() function always finds a DataGridCell with one Employee object as its content (the property of Content in DataGridCell), and can't go further into each property, no matter what column index I give it.For example, in the GetCell function, there is one line: Dim cell As DataGridCell = DirectCast(presenter.ItemContainerGenerator.ContainerFromIndex(column), DataGridCell)
,where the presenter is a DataGridCellsPresenter I got which representing the row I choose, and as soon as I give the column index, naturally I am expecting it to return the control for selected property at position I specified. But it just doesn't work as expected. Any help would be appreciated!
推荐答案
当您使用 presenter.ItemContainerGenerator.ContainerFromIndex
受到限制,它只能用于非虚拟化项目,即数据网格的滚动视图(加上滚动视图限制上下的行的偏移数量)中显示的行。
The moment you use presenter.ItemContainerGenerator.ContainerFromIndex
you fall into a limitation for it to work ONLY for non-virtualized items i.e. rows that are shown in the scroll view (plus some offset number of rows above and below the scroll view limits) of the datagrid.
要访问所有单元格的值,必须对每一行执行列级绑定。
For you to access values of all cells you will have to execute column level bindings for each row.
-
访问
DataGrid.Items
集合。这是项目的视图,因此将排除任何由过滤条件或自定义分页等隐藏的项目。如果您不希望这样做,请执行DataGrid.ItemsSource.Cast< object>()。ToList()
调用。
Access the
DataGrid.Items
collection. This is a view of items so any items hidden by filter criteria or custom paging etc will be excluded. If you dont want that then doDataGrid.ItemsSource.Cast<object>().ToList()
call.
现在访问数据网格的所有列,即 DataGrid.Columns
。假定它们是除 DataGridTemplateColumn
以外的任何类型,下面的步骤3将提取单元格级别的值。对于模板列,您将必须指定一些代表单元格整个模板的属性值。我发现 DataGridTemplateColumn.SortMemberPath
是一个很好的选择。
Now access all columns of the datagrid i.e. DataGrid.Columns
. Assuming that they are of any type but DataGridTemplateColumn
, step 3 below will extract the cell level value. For template columns you will have to specify some property value that represents the entire template of the cell. I find DataGridTemplateColumn.SortMemberPath
a good candidate for this.
提取 DataGridTextColumn.Binding
, DataGridCheckBoxColumn.Binding
, DataGridComboBoxColumn.SelectedValueBinding
或 DataGridComboBoxColumn.SelectedItemBinding
。然后,对步骤1中的每个项目执行绑定以提取值。
Extract the DataGridTextColumn.Binding
, DataGridCheckBoxColumn.Binding
, DataGridComboBoxColumn.SelectedValueBinding
or DataGridComboBoxColumn.SelectedItemBinding
. Then for each item from step 1, execute the binding to extract the value.
代码 >
private void Button_Click_1(object sender, RoutedEventArgs e)
{
string gridContent = string.Empty;
foreach(var item in MyDataGrid.Items)
{
foreach (var column in MyDataGrid.Columns)
{
var textCol = column as DataGridTextColumn;
var checkCol = column as DataGridCheckBoxColumn;
var comboCol = column as DataGridComboBoxColumn;
var templateCol = column as DataGridTemplateColumn;
if (textCol != null)
{
var propertyName = ((Binding)textCol.Binding).Path.Path;
var value
= item.GetType().GetProperty(
propertyName).GetValue(
item,
new object[] {});
if (((Binding)textCol.Binding).Converter != null)
{
value
= ((Binding)checkCol.Binding).Converter.Convert(
value,
typeof(object),
((Binding)checkCol.Binding).ConverterParameter,
((Binding)checkCol.Binding).ConverterCulture);
}
gridContent = gridContent + "\t" + value.ToString();
}
if (checkCol != null)
{
var propertyName = ((Binding)checkCol.Binding).Path.Path;
object value
= item.GetType().GetProperty(
propertyName).GetValue(
item,
new object[] { });
if (((Binding)checkCol.Binding).Converter != null)
{
value
= ((Binding)checkCol.Binding).Converter.Convert(
value,
typeof(object),
((Binding)checkCol.Binding).ConverterParameter,
((Binding)checkCol.Binding).ConverterCulture);
}
gridContent = gridContent + "\t" + value.ToString();
}
if (comboCol != null)
{
var propertyName = string.Empty;
if (comboCol.SelectedValueBinding != null)
{
propertyName
= ((Binding)comboCol.SelectedValueBinding).Path.Path;
}
else if (!string.IsNullOrEmpty(comboCol.SelectedValuePath))
{
propertyName = comboCol.SelectedValuePath;
}
else if (!string.IsNullOrEmpty(comboCol.DisplayMemberPath))
{
propertyName = comboCol.DisplayMemberPath;
}
var value = item.GetType().GetProperty(
propertyName).GetValue(
item,
new object[] { });
if (comboCol.SelectedValueBinding != null
&& ((Binding)comboCol.SelectedValueBinding).Converter != null)
{
var bnd = (Binding)comboCol.SelectedValueBinding;
value
= bnd.Converter.Convert(
value,
typeof(object),
bnd.ConverterParameter,
bnd.ConverterCulture);
}
gridContent = gridContent + "\t" + value.ToString();
}
if (templateCol != null)
{
var propertyName = templateCol.SortMemberPath;
var value
= item.GetType().GetProperty(
propertyName).GetValue(
item,
new object[] { });
gridContent = gridContent + "\t" + value.ToString();
}
}
gridContent = gridContent + "\n";
}
MessageBox.Show(gridContent);
}
}
这篇关于在WPF中访问DataGrid的单元格值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!