访问 WPF 中 DataGrid 的单元格值?

发布于 2024-12-11 13:10:11 字数 963 浏览 0 评论 0原文

我们有这样一个场景,我们有一个包含DataGrid的页面,现在我们想从这个DataGrid中获取所有数据,但不访问它的底层项目源,即我们想直接从DataGrid访问数据。这似乎很棘手,但并非不可能。我找到了很多文章,例如:DataGridHelper ,以及这个: 获取 WPF DataGrid 行和单元格,以及许多其他内容。它们基本上是相同的:在另一个 GetVisualChild 函数的帮助下定义 DataGrid 上的扩展方法来查找目标 DataGridCell 对象。然而,当我使用它时,我找不到目标细胞。具体来说,DataGrid 中的每一行对应于 DataContext 集合中的一项,比方说,它是一个“Employee”类型的集合,DataGrid 中的每一列对应于 Employee 类的一个属性,例如姓名、性别, 年龄。现在我的问题是,上述 GetCell() 函数总是找到一个以一个 Employee 对象作为其内容(DataGridCell 中 Content 的属性)的 DataGridCell,并且无法进一步深入每个属性,无论我给出什么列索引它。 例如,在GetCell函数中,有一行: 将单元格调暗为 DataGridCell = DirectCast(presenter.ItemContainerGenerator.ContainerFromIndex(colum), 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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

本王不退位尔等都是臣 2024-12-18 13:10:11

当您使用 Presenter.ItemContainerGenerator.ContainerFromIndex 时,您就会陷入限制,因为它仅适用于非虚拟化项目,即滚动视图中显示的行(加上上方和下方的一些行偏移量)数据网格的滚动视图限制)。

为了访问所有单元格的值,您必须为每行执行列级绑定。

  1. 访问DataGrid.Items集合。这是项目的视图,因此任何被过滤条件或自定义分页等隐藏的项目都将被排除。如果您不希望这样做,请执行 DataGrid.ItemsSource.Cast().ToList() 调用。

  2. 现在访问数据网格的所有列,即DataGrid.Columns。假设它们是除 DataGridTemplateColumn 之外的任何类型,下面的步骤 3 将提取单元格级别值。对于模板列,您必须指定一些代表单元格整个模板的属性值。我发现 DataGridTemplateColumn.SortMemberPath 是一个很好的选择。

  3. 提取 DataGridTextColumn.BindingDataGridCheckBoxColumn.BindingDataGridComboBoxColumn.SelectedValueBindingDataGridComboBoxColumn.SelectedItemBinding。然后,对于步骤 1 中的每个项目,执行绑定以提取值。

代码

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

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.

  1. 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 do DataGrid.ItemsSource.Cast<object>().ToList() call.

  2. 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.

  3. 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.

Code

    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);
    }
}
懒猫 2024-12-18 13:10:11

我意识到这是一个老话题,但我寻找了一个简单的解决方案并终于找到了它。认为其他人可能喜欢简单。以下示例按指定列在数据网格中搜索所需值,如果找到,将选择该行。

    private void dgSetRow(DataGrid dg, string sColHeader, int iFindValue)
    {

        foreach (DataRowView drv in dg.Items )
        {
            // compare value in datarow of view
            if (iFindValue == (int)drv.Row[sColHeader])
            {
                // select item
                dg.SelectedItem = drv;
                dg.ScrollIntoView(drv);
            }
        }
    }

I realize this is old topic, but I searched for a simple solution and finally found it. Thought others might like simple. The following example searches the datagrid by specified column for the desired value, if found will select the row.

    private void dgSetRow(DataGrid dg, string sColHeader, int iFindValue)
    {

        foreach (DataRowView drv in dg.Items )
        {
            // compare value in datarow of view
            if (iFindValue == (int)drv.Row[sColHeader])
            {
                // select item
                dg.SelectedItem = drv;
                dg.ScrollIntoView(drv);
            }
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文