我的表单上有一个 DataGridView,其中有一个 ComboBox 列。
当表单加载时,网格没有数据源,因为它是通过用户触发的另一种方法加载到网格的。
加载表单时(创建表单实例),我收到错误:
索引超出范围。必须为非负数且小于集合的大小。
当为列设置标题文本时,我已将其范围缩小到表单设计器文件中的行。这是导致 Form1.Designer.cs 文件中出现错误的代码行:
this.gridComboBox1.HeaderText = "Options";
如果我注释掉这一行,表单加载不会出现问题,但网格中组合框列的标题只是“gridComboBox1”,这显然不理想。
我正在使用 Visual Studio 创建表单,因此尝试从工具箱向应用程序添加一个全新的 datagridview 控件并设置列,而不更改除设置列类型和标题文本之外的任何设置。但我遇到了同样的问题,这让我认为这是 winforms 的一个问题,因为它提供了不起作用的功能。
如果我尝试以编程方式更改表单的加载事件中的标题文本,也会遇到相同的错误。
我对 C# 还很陌生,一直无法弄清楚为什么会发生这种情况。该列本身是在设计器文件的代码中较早添加的,如下所示:
this.dgv1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.select,
this.gridComboBox1,
this.DataType});
所以该列应该供后面的代码交互。
有人能够解释为什么会这样吗,因为这对我来说毫无意义。
我现在做了更多调查,我相信我已经解决了这个问题。
我订阅 CellValueChanged 事件以触发一些代码,这些代码根据从 ComboBox 列中选择的选项填充网格中的另一列。
但是,当设计器代码设置标题文本时,会触发此事件。
这是有问题的代码:
private void dgv1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
try
{
if (e.ColumnIndex == 1) // index of the combobox column
{
string mappedField = dgv1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
string sql = @$"SELECT
UPPER(DATA_TYPE)
+ CASE
WHEN DATA_TYPE IN ('nvarchar', 'varchar') AND CHARACTER_MAXIMUM_LENGTH = -1 THEN '(MAX)'
WHEN DATA_TYPE IN ('nvarchar', 'varchar') THEN '('+CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10)) + ')'
ELSE ''
END AS DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Report'
AND COLUMN_NAME = '{mappedField}';";
string targetDataType = clsRepeatableMethods.SQLOutputToStringVariable(sql, clsConnections.ConnStrStg);
dgv1.Rows[e.RowIndex].Cells["RepDataType"].Value = targetDataType;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
由于设计者创建网格时网格中除标题行外没有任何行,因此返回索引超出范围错误。
修复方法是同时检查行索引。
我更改了这行代码:
if (e.ColumnIndex == 1)
对此:
if (e.RowIndex != -1 && e.ColumnIndex == 1)
现在一切正常了。
感谢@Sinatr,他的评论让我进一步了解可以触发哪些其他代码。