如何避免 datagridrow 突出显示函数在 Null 上轰炸?

How do I avoid datagridrow highlight function bombing out on Null?

提问人:user2970749 提问时间:1/20/2021 更新时间:1/22/2021 访问量:39

问:

我有一个函数,旨在突出显示某些单元格彼此不匹配的行。这一直有效,直到它命中一个不包含任何内容的单元格,然后它作为 nullrefexception 轰炸出来。我知道我在这里错过了一些简单的东西,但我正在用头撞墙试图弄清楚! 提前致谢。

        private void highlightrow()
    {
        int rowcnt = 0;
        dataGridView1.ClearSelection();
        int deviceNameColIndex = dataGridView1.Columns["cDeviceName"].Index;
        int deviceNameColIndex2 = dataGridView1.Columns["cDeviceName2"].Index;
        int driverVerColIndex = dataGridView1.Columns["cDriverVersion"].Index;
        int driverVerColIndex2 = dataGridView1.Columns["cDriverVersion2"].Index;
        int driverProviderName = dataGridView1.Columns["cdriverProviderName"].Index;
        int driverProviderName2 = dataGridView1.Columns["cdriverProviderName2"].Index;

        try
        {
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {

                rowcnt++;

                if (row.Cells[driverVerColIndex].Value.ToString() != row.Cells[driverVerColIndex2].Value.ToString() ||
                    row.Cells[driverProviderName].Value.ToString() != row.Cells[driverProviderName2].Value.ToString() ||
                    row.Cells[deviceNameColIndex].Value.ToString() != row.Cells[deviceNameColIndex2].Value.ToString()
                    )
                {
                    dataGridView1.DefaultCellStyle.SelectionBackColor = Color.YellowGreen;
                    row.Selected = true;
                }

            }
        }

        catch (NullReferenceException) { }
 }

How do I skip null cells?

DataGridView NullReferenceException 突出显示

评论

0赞 JohnG 1/21/2021
对于网格中的任何单元格,在尝试调用其方法之前,应检查以确保单元格不是 NOT。所有的台词......假设单元格不是,并且显然一个或多个单元格是并且正在抛出空引用异常。你应该“检查”以确保不是......在你调用它的方法之前。例如,如果 grids 属性为 ...然后,“new”行中的单元格将是ValuenullToStringrow.Cells[xxx].Value.ToString()ValuenullnullValuenullif (row.Cells[driverVerColIndex].Value != null) {…}ToStringAllowUsersToAddRowstruenull.
1赞 JohnG 1/21/2021
这回答了你的问题吗?什么是 NullReferenceException,如何修复它?

答:

0赞 user2970749 1/21/2021 #1

谢谢你的想法。我以前尝试过检查空值,但仍然遇到问题,所以正在寻找一些实际的例子。碰巧的是,我已经设法对其进行了排序,尽管仍然觉得可以做得更好:

private void highlightrow()
{
    int rowcnt = 0;
    dataGridView1.ClearSelection();
    int deviceNameColIndex = dataGridView1.Columns["cDeviceName"].Index;
    int deviceNameColIndex2 = dataGridView1.Columns["cDeviceName2"].Index;
    int driverVerColIndex = dataGridView1.Columns["cDriverVersion"].Index;
    int driverVerColIndex2 = dataGridView1.Columns["cDriverVersion2"].Index;
    int driverProviderName = dataGridView1.Columns["cdriverProviderName"].Index;
    int driverProviderName2 = dataGridView1.Columns["cdriverProviderName2"].Index;

    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        rowcnt++;

        foreach (DataGridViewCell cell in row.Cells)
        {
            string val = cell.Value as string;
            if (String.IsNullOrEmpty(val))
            { }
            else
            {
                try
                {
                    if (
                    row.Cells[driverVerColIndex].Value.ToString() != row.Cells[driverVerColIndex2].Value.ToString() ||
                    row.Cells[driverProviderName].Value.ToString() != row.Cells[driverProviderName2].Value.ToString() ||
                    row.Cells[deviceNameColIndex].Value.ToString() != row.Cells[deviceNameColIndex2].Value.ToString()
                    )
                    {
                        dataGridView1.DefaultCellStyle.SelectionBackColor = Color.YellowGreen;
                        row.Selected = true;
                    }
                }
                catch { }
            }
        }

    }
}

评论

0赞 JohnG 1/21/2021
通过列添加的循环可能会捕获单元格的值,但是,如果单元格不是,那么代码将执行该语句,每行至少六 (6) 次比较不同的单元格,而它只需要为每行执行一次?你确定这是一个好的解决方案吗?nullnullif
0赞 JohnG 1/21/2021
此外,如果一行中的一个或多个单元格是 AND 并且同一行中的一个或多个单元格不是 NOT,则代码仍将失败并引发 null 异常换句话说,代码只会起作用而不会引发异常......如果一行中的所有单元格都是 NOT 或一行中的所有单元格都不是 任何其他情况都将引发 null 异常。nullnull.nullnull.
0赞 user2970749 1/22/2021
我绝对不是说这是一个很好的解决方案,并且认为可能有一个更好的解决方案!可能会抛出异常(尚未实际测试过),但突出显示功能正在工作到最后,这是以前没有的。我愿意以任何方式接受更好的建议(可能不难!
0赞 JohnG 1/22/2021 #2

我的评论没有冒犯的意思。我只是想推动你找到一个更好的解决方案。你是否选择尝试寻找更好的解决方案取决于你。为了捍卫我的评论,特别是关于通过列的循环正在产生的不良副作用......我只是想指出“为什么”这种方法会产生一些不希望/意想不到的结果。如果它不是有用的评论,请原谅我。foreach

使用当前发布的示例,下面是一种可能的“更好”方法,当尝试避免 null 引用异常时,特别是在循环遍历DataGridView.

对于初学者来说,当遍历网格中的行并检查单元格值时,单元格值“总是”有可能在某些情况下,您“可能”假设单元格值不是,但是,即使在极少数情况下,作为编码员,如果单元格“以某种方式”并且代码没有检查这一点......然后代码崩溃。后果太严重,不能忽视此检查。null.null,null

因此,当循环遍历网格的单元格时......在我们尝试调用其方法之前检查这些值是明智的。nullToString

检查值的一个地方是该行是否为网格“新”行。如果 grid 的属性设置为 AND 且 grids 数据源允许新行,则可以保证该行中的单元格为 null。因此,在遍历行时,检查此新行将消除检查单元格的需要。我们知道它们都是这样,所以我们可以“跳过”那一行。nullAllowUsersToAddRowstruenull

您可以考虑简单地将 grids 属性更改为并跳过此检查,但是,如果以后该属性更改为 ?如果我们“总是”检查这个“新”行,无论它是否存在,都将允许代码工作,而不管属性是什么。AllowUserToAddRowsfalsetrueAllowUserToAddRows

因此,在循环中通过行的第一次检查将是对新行的检查......foreach

foreach (DataGridViewRow row in dataGridView1.Rows) {
  if (!row.IsNewRow) { … //this row it NOT the new row … }

这将消除“新”行;但是,我们仍然需要检查每个单元格。在这种情况下,代码必须检查六 (6) 个值,然后代码需要一次比较六个 (6) 个值两个。使用一堆语句可能会变得混乱。Cell.Valuenullif

因此,如果我们创建一个方法来检查两个单元格值并返回单元格值是否相等以及是否不相等,它可能会有所帮助。这应该会减少我们需要的语句数量。这种方法可能看起来像......truefalseif

private bool CellsAreEqual(DataGridViewCell cell1, DataGridViewCell cell2) {
  if (cell1.Value == null && cell2.Value == null) {
    return false;
  }
  if (cell1.Value != null && cell2.Value != null) {
    return cell1.Value.ToString().Equals(cell2.Value.ToString());
  }
  else {
    // one cell is null the other cell is not null
    return false;
  }

代码逻辑假定,如果一个或两个单元格是 ,则单元格不相等。首先检查两个单元格是否都是,如果是,则返回 如果一个单元格是而另一个单元格不是,则返回 ,否则我们可以安全地调用每个方法。nullnullfalse.nullnullfalseCell.Value.ToString

最后,使用上述方法和新的行信息,我们可以将方法更改为类似...highlightrow

private void highlightrow() {
  dataGridView1.ClearSelection();
  foreach (DataGridViewRow row in dataGridView1.Rows) {
    if (!row.IsNewRow) {
      if (!CellsAreEqual(row.Cells["cDriverVersion"], row.Cells["cDriverVersion2"]) ||
          !CellsAreEqual(row.Cells["cdriverProviderName"], row.Cells["cdriverProviderName2"]) ||
          !CellsAreEqual(row.Cells["cDeviceName"], row.Cells["cDeviceName2"])) {
        dataGridView1.DefaultCellStyle.SelectionBackColor = Color.YellowGreen;
        row.Selected = true;
      }
    }
    else {
      // ignore new row
    }
  }
}

我希望这是有道理的。

评论

0赞 user2970749 1/23/2021
首先,完全没有冒犯!我知道在某个地方可以找到更好的解决方案。其次,感谢您的深入解释和示例。这些工作完美,我已经用这个解决方案替换了我的代码。我同意这要好得多。非常感谢您在这里的努力。