0

我想访问 DataGrid 中的元素。我正在使用以下代码。但是我无法获取 DataGrid 的行。我得到空值。我只想知道为什么我得到空值以及如何解决这个问题.

 int itemscount = (dgMtHdr.Items.Count);
                dgMtHdr.UpdateLayout();
                for (int rowidx = 0; rowidx < itemscount; rowidx++)
                {

                    Microsoft.Windows.Controls.DataGridRow dgrow = (Microsoft.Windows.Controls.DataGridRow)this.dgMtHdr.ItemContainerGenerator.ContainerFromIndex(rowidx);

                    if (dgrow != null)
                    {
                        DataRow dr = ((DataRowView)dgrow.Item).Row;
                        if (dr != null)
                        {

                                obj = new WPFDataGrid();
                                Microsoft.Windows.Controls.DataGridCell cells = obj.GetCell(dgMtHdr, rowidx, 7);
                                if (cells != null)
                                {
                                    ContentPresenter panel = cells.Content as ContentPresenter;
                                    if (panel != null)
                                    {
                                        ComboBox cmb = obj.GetVisualChild<ComboBox>(panel);
                }
                }
            }
        }
       }
4

1 回答 1

1

DataGrid内部托管项目,DataGridRowsPresenter其中派生自VirtualizingStackPanelwhich 意味着默认情况下在 UI 上呈现的项目支持虚拟化,即ItemContainer不会为尚未在 UI 上呈现的项目生成。

这就是为什么null当您尝试获取未在 UI 上呈现的行时得到的原因。

因此,如果您准备好与虚拟化进行权衡,您可以turn off the Virtualization这样 -

<DataGrid x:Name="dgMtHdr" VirtualizingStackPanel.IsVirtualizing="False"/>

现在,DataGridRow对于任何索引值都不会为空。

或者

您可以通过手动调用UpdateLayout()ScrollIntoView()索引来获取该行,以便为您生成容器。有关详细信息,请参阅此处的链接。从链接 -

if (row == null)
{
    // May be virtualized, bring into view and try again.
    grid.UpdateLayout();
    grid.ScrollIntoView(grid.Items[index]);
    row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
}

编辑

由于您DataGrid位于尚未呈现的第二个选项卡中。这就是为什么它ItemContainerGenerator没有生成项目所需的相应容器的原因。因此,一旦通过挂钩StausChanged事件生成项目容器,您就需要这样做 -

   dgMtHdr.ItemContainerGenerator.StatusChanged += new 
      EventHandler(ItemContainerGenerator_StatusChanged);

    void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
    {
        if ((sender as ItemContainerGenerator).Status == 
               GeneratorStatus.ContainersGenerated)
        {
            // ---- Do your work here and you will get rows as you intended ----

            // Make sure to unhook event here, otherwise it will be called 
            // unnecessarily on every status changed and moreover its good
            // practise to unhook events if not in use to avoid any memory
            // leak issue in future.

            dgMtHdr.ItemContainerGenerator.StatusChanged -= 
                                ItemContainerGenerator_StatusChanged;
        }
    }
于 2013-04-14T17:11:08.437 回答