0

I want to access the elements in the DataGrid.I am using following code.But I am unable to get the row of DataGrid.I am getting null value.I just want to know why I am getting null value and how to resolve this issue.

 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);
                }
                }
            }
        }
       }
cas001s
  • 1
  • 3

1 Answers1

1

DataGrid internally hosts items in DataGridRowsPresenter which derives from VirtualizingStackPanel which means items rendered on UI by default support Virtualization i.e. ItemContainer won't be generated for items which are not rendered on UI yet.

That's why you getting null when you try to fetch rows which are not rendered on UI.

So, in case you are ready to trade off with Virtualization, you can turn off the Virtualization like this -

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

Now, DataGridRow won't be null for any index value.

OR

You can get the row by manually calling UpdateLayout() and ScrollIntoView() for the index so that container gets generated for you. For details refer to this link here. From the link -

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

EDIT

Since your DataGrid is in second tab which is not rendered yet. That's why its ItemContainerGenerator haven't generated corresponding containers required for items. So, you need to do it once item container is generated by hooking to StausChanged event -

   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;
        }
    }
Community
  • 1
  • 1
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
  • Hi Rohit,Thanks for giving reply.I tried both options.But still my problem not resolved. – cas001s Apr 15 '13 at 05:35
  • I guess your Datagrid is not rendered yet on UI when you are running this code. Where have you placed this code and can you update your DataGrid Xaml in question? – Rohit Vats Apr 15 '13 at 16:58
  • Hi Rohit,In a button click event i am calling one function in which I placed this code. – cas001s Apr 15 '13 at 17:06
  • Can you check by placing breakpoint in your code just before fetching row that `itemContainerGenerator` status is `ContainersGenerated`. You can check with this piece of code - `bool status = dgMtHdr.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated;` – Rohit Vats Apr 15 '13 at 17:20
  • Hi Rohit,I am getting status as NotStarted.One more thing I just want to inform you is actually my display window is having two tabs.In the first tab there is a button.In it's click event I need to load the data conditionally into the DataGrid which is present in the second tab.So I am accessing second tab DataGrid in the button click event logic.Before the accessing the DataGrid I called the focus method of the second tab. – cas001s Apr 16 '13 at 04:45
  • That's an issue since `DataGrid` on second tab is not rendered yet and hence `ItemContainer` won't be generated for it. However, there is workaround for it, i have updated in the answer. See, if it helps. – Rohit Vats Apr 19 '13 at 17:55