如何避免 datagridrow 高亮功能在 Null 上爆炸?
How do I avoid datagridrow highlight function bombing out on Null?
我有一个函数,旨在突出显示某些单元格彼此不匹配的行。这一直有效,直到它碰到一个什么都不包含的单元格,然后它作为 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?
谢谢你的想法。我之前尝试过检查 null 但仍然遇到问题,所以一直在寻找一些实际的例子。碰巧的是,我设法对它进行了排序,但仍然觉得可以做得更好:
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 { }
}
}
}
}
我的评论没有冒犯的意思。我只是想推动您找到更好的解决方案。您是否选择尝试寻找更好的解决方案取决于您。为了捍卫我的评论,特别是关于 foreach
列循环产生的不良副作用......我只是想指出“为什么”这种方法会产生一些 undesired/unexpected 结果.如果它不是有用的评论,请原谅我。
使用当前发布的示例,下面是一种可能的“更好”方法,当试图避免空引用异常时,特别是在循环 DataGridView.
时
对于初学者来说,当遍历网格中的行并检查单元格值时,单元格值“总是”可能是 null.
在某些情况下,您“可能”假设单元格值不是 null,
然而,即使在极少数情况下,作为编码器,如果单元格“不知何故” null
并且代码不检查这个......然后代码崩溃。后果太严重了,不能忽略这个检查。
因此,当遍历网格的单元格时...在我们尝试调用它的 ToString
方法之前检查这些 null
值是明智的。
检查 null
值的一个地方是该行是否是网格“新”行。如果网格的 AllowUsersToAddRows
属性 设置为 true
并且网格数据源允许新行,那么可以保证该行中的单元格为空。因此,在遍历行时,检查这个新行将消除检查单元格的需要。我们知道它们都是 null
所以我们可以“跳过”那一行。
您可以考虑简单地将网格 AllowUserToAddRows
属性 更改为 false
并跳过此检查,但是,如果以后 属性 被更改怎么办到 true
?如果我们“始终”检查这个“新”行,无论它是否存在,都将允许代码工作,而不管 AllowUserToAddRows
属性 是什么。
因此,foreach
循环遍历行的第一个检查将是对新行的检查……
foreach (DataGridViewRow row in dataGridView1.Rows) {
if (!row.IsNewRow) { … //this row it NOT the new row … }
这消除了“新”行;但是,我们仍然需要检查每个单元格。在这种情况下,代码必须检查六 (6) 个 Cell.Value
是否为 null
,然后代码将需要一次比较六 (6) 个值。使用一堆 if
语句可能会变得混乱。
因此,如果我们创建一个检查两个单元格值的方法,如果单元格值相等,returns true
,如果不相等,则 false
可能会有所帮助。这应该会减少我们需要的 if
语句的数量。这个方法可能看起来像……
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;
}
代码逻辑假定,如果一个或两个单元格是 null
,则单元格不相等。首先检查是否两个单元格都是 null
如果是 returns false.
如果一个单元格是 null
而另一个单元格不是 null
,然后return false
,否则我们可以安全地调用每个Cell.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
}
}
}
我希望这是有道理的。
我有一个函数,旨在突出显示某些单元格彼此不匹配的行。这一直有效,直到它碰到一个什么都不包含的单元格,然后它作为 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?
谢谢你的想法。我之前尝试过检查 null 但仍然遇到问题,所以一直在寻找一些实际的例子。碰巧的是,我设法对它进行了排序,但仍然觉得可以做得更好:
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 { }
}
}
}
}
我的评论没有冒犯的意思。我只是想推动您找到更好的解决方案。您是否选择尝试寻找更好的解决方案取决于您。为了捍卫我的评论,特别是关于 foreach
列循环产生的不良副作用......我只是想指出“为什么”这种方法会产生一些 undesired/unexpected 结果.如果它不是有用的评论,请原谅我。
使用当前发布的示例,下面是一种可能的“更好”方法,当试图避免空引用异常时,特别是在循环 DataGridView.
对于初学者来说,当遍历网格中的行并检查单元格值时,单元格值“总是”可能是 null.
在某些情况下,您“可能”假设单元格值不是 null,
然而,即使在极少数情况下,作为编码器,如果单元格“不知何故” null
并且代码不检查这个......然后代码崩溃。后果太严重了,不能忽略这个检查。
因此,当遍历网格的单元格时...在我们尝试调用它的 ToString
方法之前检查这些 null
值是明智的。
检查 null
值的一个地方是该行是否是网格“新”行。如果网格的 AllowUsersToAddRows
属性 设置为 true
并且网格数据源允许新行,那么可以保证该行中的单元格为空。因此,在遍历行时,检查这个新行将消除检查单元格的需要。我们知道它们都是 null
所以我们可以“跳过”那一行。
您可以考虑简单地将网格 AllowUserToAddRows
属性 更改为 false
并跳过此检查,但是,如果以后 属性 被更改怎么办到 true
?如果我们“始终”检查这个“新”行,无论它是否存在,都将允许代码工作,而不管 AllowUserToAddRows
属性 是什么。
因此,foreach
循环遍历行的第一个检查将是对新行的检查……
foreach (DataGridViewRow row in dataGridView1.Rows) {
if (!row.IsNewRow) { … //this row it NOT the new row … }
这消除了“新”行;但是,我们仍然需要检查每个单元格。在这种情况下,代码必须检查六 (6) 个 Cell.Value
是否为 null
,然后代码将需要一次比较六 (6) 个值。使用一堆 if
语句可能会变得混乱。
因此,如果我们创建一个检查两个单元格值的方法,如果单元格值相等,returns true
,如果不相等,则 false
可能会有所帮助。这应该会减少我们需要的 if
语句的数量。这个方法可能看起来像……
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;
}
代码逻辑假定,如果一个或两个单元格是 null
,则单元格不相等。首先检查是否两个单元格都是 null
如果是 returns false.
如果一个单元格是 null
而另一个单元格不是 null
,然后return false
,否则我们可以安全地调用每个Cell.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
}
}
}
我希望这是有道理的。