ASP.NET C# GridView调用Rows[index]抛出索引超出范围异常
GridView行选择时索引超出范围问题排查
问题背景
开发用于在GridView控件中展示SQL数据表存储的可用门店信息的用户控件,供用户选择后填充对应文本框。目前已完成GridView全量数据绑定,每行内置的选择按钮可正常触发操作,但存在以下异常:
- 使用
Rows[index]语法获取行对象时,无法将单元格值提取到变量,抛出索引超出范围异常 - 调试确认获取的索引值完全正确,手动将索引值设为0、1测试仍触发相同错误,表现如同GridView内不存在任何数据行
- 实现逻辑:使用ButtonField作为选择按钮,触发GridView的
OnRowCommand事件执行选择逻辑 - 已排查常见错误诱因:不存在索引值为负数、未配置
DataKeyNames属性的问题,始终无法修复错误
相关实现代码
GridView前端代码
<asp:GridView ID="gvStore" runat="server" AutoGenerateColumns="False" Visible="false" DataKeyNames="Name" OnRowCommand="gvExecSelectSTR_RowCommand"> <Columns> <asp:BoundField DataField="Name" HeaderText="Name" /> <asp:ButtonField ButtonType="Link" Text="Select" CommandName="SelectStore"/> </Columns> </asp:GridView>
行选择后台事件代码
protected void gvExecSelectSTR_RowCommand(object sender, GridViewCommandEventArgs e) { if (e.CommandName == "SelectStore") { int index = Convert.ToInt32(e.CommandArgument); // 调试确认此处获取的行索引值正确 GridViewRow row = gvStore.Rows[index]; // 该行触发索引超出范围错误 IDStore.Text = row.Cells[0].Text; } }
GridView数据绑定方法代码
private void GridViewStore() { try { DataTable StoreTable = new DataTable(); StoreTable.Columns.AddRange(new DataColumn[1] { new DataColumn("Name",typeof(string)) }); // 内部SQL逻辑省略:执行查询语句将门店结果加载到DataReader对象readerStore中 if (readerStore.HasRows) { while (readerStore.Read()) { StoreTable.Rows.Add(readerStore["Name"].ToString()); } } gvStore.DataSource = StoreTable; gvStore.DataBind(); readerStore.Close(); } catch (Exception ex) { OnErrorOccurred(new ErrorOccurredEventArgs("Grid View Bind Message" + ex.Message, ex)); } }
错误原因与修复方案
错误和索引值、DataKey配置无关,核心诱因是ASP.NET WebForms页面生命周期下,GridView数据绑定/状态加载时机错误:
- 未正确处理页面回发时的GridView数据加载逻辑:如果仅在首次页面加载、或点击其他按钮时调用
GridViewStore()绑定数据,点击选择按钮触发回发后,RowCommand事件执行前,GridView未从视图状态恢复行数据、也未重新执行绑定,此时gvStore.Rows集合长度为0,传入任何合法索引都会触发超出范围错误。 - GridView初始设置了
Visible="false",如果回发时控件仍处于隐藏状态,部分.NET框架版本不会初始化行集合,也会导致该错误。
修复操作:
- 在
Page_Load事件中补充绑定逻辑,首次加载时完成数据绑定,同时确认GridView开启视图状态(默认开启,无需额外修改),让回发时控件自动从视图状态恢复行数据:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 首次页面加载时绑定门店数据 GridViewStore(); } }
- 调整事件执行顺序:如果业务逻辑是点击其他按钮才显示门店GridView,要先设置
gvStore.Visible = true、完成数据绑定,再响应行选择的RowCommand事件,不要在选择事件触发后才绑定数据或显示控件。 - 替换取值逻辑:既然已经配置了
DataKeyNames="Name",不需要从单元格读取文本,直接通过DataKey集合获取值即可,既不受Rows集合加载时机影响,也能避免单元格索引调整导致的取值错误:
protected void gvExecSelectSTR_RowCommand(object sender, GridViewCommandEventArgs e) { if (e.CommandName == "SelectStore") { int index = Convert.ToInt32(e.CommandArgument); IDStore.Text = gvStore.DataKeys[index].Value.ToString(); } }
内容的提问来源于stack exchange,提问作者ManuelGomez
相关产品推荐
相关产品推荐

