如何避免DataGridView添加重复行?现有代码无效求解决方案
Fixing DataGridView Duplicate Prevention in C#
Let's break down the issues in your current code and fix them step by step:
Issues with Your Current Code
- Index Out-of-Bounds Error: Your loop uses
i <= dgvOC.Rows.Count, but DataGridView rows are zero-indexed. This means wheniequalsRows.Count, you're trying to access a row that doesn't exist, which will throw anIndexOutOfRangeException. - Incomplete Logic: You only check for duplicates but don't actually prevent adding a new row when a duplicate is found. Also, you only add a row when the grid is empty—there's no code to add a row if no duplicates are found when the grid has existing rows.
- Null Reference Risk: If
dgvOC.Rows[i].Cells[0].Valueisnull, callingToString()will crash your app.
Corrected Solution
Here's a revised version that properly handles duplicate checks, avoids errors, and implements the expected behavior:
// Flag to track if a duplicate product is found bool duplicateFound = false; // Iterate through existing rows (use < instead of <= to avoid index errors) for (int i = 0; i < dgvOC.Rows.Count; i++) { // Skip the new row if your DataGridView allows user to add rows (it has an empty row at the end) if (dgvOC.Rows[i].IsNewRow) continue; // Safely get the product name from the cell, handle null values string existingProduct = dgvOC.Rows[i].Cells[0].Value?.ToString() ?? string.Empty; string newProduct = txtProd.Text.Trim(); // Trim whitespace to avoid accidental duplicates if (string.Equals(existingProduct, newProduct, StringComparison.OrdinalIgnoreCase)) { duplicateFound = true; break; // No need to check further once a duplicate is found } } if (duplicateFound) { MessageBox.Show("Usted ya ha agregado un producto con el mismo nombre. Modifique la cantidad o borre el producto para agregar una nueva entrada."); } else { // Add the new row since no duplicates were found dgvOC.Rows.Add(txtProd.Text.Trim(), numCant.Value, txtTipo.Text, precioGuardado, precioGuardado * (int)numCant.Value); }
Key Improvements
- Safe Indexing: Uses
i < dgvOC.Rows.Countto avoid accessing non-existent rows, and skips theIsNewRowif your grid enables user row addition. - Null Safety: Uses the null-conditional operator (
?.) and null-coalescing operator (??) to handle cases where the cell value might be null. - Case-Insensitive Check: Uses
StringComparison.OrdinalIgnoreCaseto treat "ProductA" and "producta" as duplicates (remove this if you want case-sensitive checks). - Proper Flow Control: Sets a flag when a duplicate is found, then either shows a message or adds the new row based on that flag.
- Whitespace Handling: Trims the input product name to prevent duplicates caused by extra spaces.
Bonus: Updating Quantity Instead of Blocking
If you'd prefer to update the existing product's quantity instead of just blocking the addition, you can modify the loop to find the duplicate row and adjust its value:
bool duplicateFound = false; int duplicateRowIndex = -1; for (int i = 0; i < dgvOC.Rows.Count; i++) { if (dgvOC.Rows[i].IsNewRow) continue; string existingProduct = dgvOC.Rows[i].Cells[0].Value?.ToString() ?? string.Empty; string newProduct = txtProd.Text.Trim(); if (string.Equals(existingProduct, newProduct, StringComparison.OrdinalIgnoreCase)) { duplicateFound = true; duplicateRowIndex = i; break; } } if (duplicateFound) { // Get current quantity and add the new quantity int currentQuantity = Convert.ToInt32(dgvOC.Rows[duplicateRowIndex].Cells[1].Value); int newQuantity = currentQuantity + (int)numCant.Value; // Update the quantity and total price cells dgvOC.Rows[duplicateRowIndex].Cells[1].Value = newQuantity; dgvOC.Rows[duplicateRowIndex].Cells[4].Value = precioGuardado * newQuantity; MessageBox.Show("Producto existente encontrado. Cantidad actualizada."); } else { dgvOC.Rows.Add(txtProd.Text.Trim(), numCant.Value, txtTipo.Text, precioGuardado, precioGuardado * (int)numCant.Value); }
This way, users don't have to manually modify existing rows—your app handles updating the quantity automatically!
内容的提问来源于stack exchange,提问作者Newbee4Ever
相关产品推荐
相关产品推荐

