1

I want to pass a value and a column index to a method that will programmatically select the rows in a DataGrid control that match the value in the given column.

My code is like this:

private void HighlightSelections(string selection, int colIndex)
{
    mtoDG.UnselectAll();
    for(int i = 0; i < mtoDG.Items.Count; i++)
    {
        DataGridRow row = mtoDG.ItemContainerGenerator.ContainerFromIndex(i) as DataGridRow;
        if (mtoDG.Columns[colIndex].GetCellContent(row) is TextBlock cellContent && cellContent.Text.Equals(selection))
            {
                object item = mtoDG.Items[i];
                mtoDG.SelectedItems.Add(item);
            }
        }
    }

I have found that this method only works if the entirety of the datagrid is displayed on the screen. If there are any undisplayed rows due to space constraint then it will throw a nullexception error.

So my question is is there anything I can change in my code to make it work even if there are unseen rows in the display area?

Aowei Xu
  • 61
  • 4
  • Welcome to stack overflow! Could you include the stack trace of your `NullReferenceException` in your question? It should be available as text in the output tool window (or the console, depending on how you're running your project) – clarkitect Sep 11 '18 at 05:14
  • @clarkitect Hi, and thanks. Is this what you meant: An unhandled exception of type 'System.ArgumentNullException' occurred in PresentationFramework.dll Value cannot be null. – Aowei Xu Sep 11 '18 at 05:26

3 Answers3

0

Firstly, handle the ArgumentNullException by adding row != null:

DataGridRow row = mtoDG.ItemContainerGenerator.ContainerFromIndex(i) as DataGridRow;
if (row != null)
{
    if (mtoDG.Columns[colIndex].GetCellContent(row) is TextBlock cellContent && cellContent.Text.Equals(selection))
    {
        object item = mtoDG.Items[i];
        mtoDG.SelectedItems.Add(item);
    }
}

Secondly, subscribe the ItemContainerGenerator.StatusChanged event to refresh the HighlightSelections:

mtoDG.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;

private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
    // HighlightSelections(?, ?);
}
Iron
  • 926
  • 1
  • 5
  • 16
  • This has worked for me, although it's a bit slow for selections made in larger grids, but I can try to improve on that later. Thanks! – Aowei Xu Sep 11 '18 at 14:15
0

The good solution here is to have DataContext with IsSelected property for rows, then you should just binding it with row IsSelected, after that you can just set your DataContext property and everything should be OK, because your DataContext always have valid items.

Ilya Grigoryan
  • 229
  • 1
  • 5
0

I think you need to find out what caused the ArgumentNullException first. Disable DataGrid virtualization feature may help.

Zion Yang
  • 21
  • 1
  • 3