ASP.NET动态为MultiView添加View及切换按钮报错解决方法
问题根本原因
- ASP.NET 动态创建的服务器控件不会被自动持久化,每次页面回发(包括UpdatePanel的异步回发)都会丢失,必须在每次回发时提前重建
- 现有View创建逻辑写在MultiView的Load事件中,且仅在DropDownList4.SelectedIndex>0时执行,按钮点击事件的执行优先级晚于Load事件,修改ActiveViewIndex时所有动态View尚未重建,Views集合计数为0,因此触发索引越界错误
- 现有Button4(下一步)的点击逻辑仅修改了TextBox2的文本,未实际更新MultiView的ActiveViewIndex,逻辑存在错误
- 原有SQL查询采用字符串拼接方式,存在SQL注入风险
修复方案
1. 调整控件重建逻辑
将动态View的创建逻辑移到Page_Init事件中,每次回发都重建已选择条件对应的View,同时将依赖的下拉框选择值存入ViewState确保回发可读取:
protected void Page_Init(object sender, EventArgs e) { // 回发时如果已经有选择的项目,提前重建所有View if (IsPostBack && ViewState["SelectedProject"] != null && ViewState["SelectedScheduleCond"] != null) { string project = ViewState["SelectedProject"].ToString(); int scheduleCond = Convert.ToInt32(ViewState["SelectedScheduleCond"]); if (scheduleCond > 0) { BuildViews(project); } } } // 抽离View创建公共方法,避免重复代码 private void BuildViews(string project) { int i = 1; // 改为参数化查询,避免SQL注入 SqlCommand cmd = new SqlCommand("select DISTINCT(schedule) from tender where project = @project", agr); cmd.Parameters.AddWithValue("@project", project); SqlDataReader dr = cmd.ExecuteReader(); while (dr.Read()) { string schedule = dr[0].ToString().Trim(); GridView Gridview1 = new GridView(); Gridview1.ID = "Gridview" + i.ToString(); Gridview1.RowDataBound += new GridViewRowEventHandler(Gridview1_RowDataBound); Gridview1.EnableViewState = true; Gridview1.HeaderStyle.BackColor = System.Drawing.Color.Silver; Gridview1.HeaderStyle.ForeColor = System.Drawing.Color.White; Gridview1.HeaderStyle.Font.Bold = true; Gridview1.ForeColor = System.Drawing.Color.Gray; Gridview1.AlternatingRowStyle.BackColor = System.Drawing.Color.White; Gridview1.GridLines = GridLines.None; Gridview1.RowStyle.BackColor = System.Drawing.ColorTranslator.FromHtml("#EFF3FB"); Gridview1.HorizontalAlign = HorizontalAlign.Center; Gridview1.Width = 900; DataTable dt = new DataTable(); dt.Columns.Add("SN", typeof(string)); dt.Columns.Add("SCHEDULE", typeof(string)); dt.Columns.Add("MATERIAL", typeof(string)); dt.Columns.Add("UNIT", typeof(string)); dt.Columns.Add("PREVIOUS BOQ QTY", typeof(string)); dt.Columns.Add("CURRENT QTY", typeof(string)); int j = 1; // 同样改为参数化查询 SqlCommand cmd1 = new SqlCommand("select material from tender where project = @project AND schedule = @schedule order by schedulesubsn ", agr); cmd1.Parameters.AddWithValue("@project", project); cmd1.Parameters.AddWithValue("@schedule", schedule); SqlDataReader dr1 = cmd1.ExecuteReader(); while (dr1.Read()) { DataRow row = dt.NewRow(); string mat = dr1[0].ToString().Trim(); row["SN"] = j; row["SCHEDULE"] = schedule; row["MATERIAL"] = mat; row["UNIT"] = Calfunc.getunit(mat); row["PREVIOUS BOQ QTY"] = Calfunc.GetLocationBOQ(DropDownList1.SelectedItem.ToString(), DropDownList2.SelectedItem.ToString(), DropDownList3.SelectedItem.ToString(), DropDownList4.SelectedItem.ToString(), schedule, mat); dt.Rows.Add(row); j++; } dr1.Dispose(); View view = new View(); view.ID = schedule; view.Controls.Add(Gridview1); MultiView1.Views.Add(view); Gridview1.DataSource = dt; Gridview1.DataBind(); i++; } dr.Dispose(); }
2. 修改原MultiView1_Load事件逻辑
仅在首次加载或下拉框选择变更时存储选择条件、触发View重建:
protected void MultiView1_Load(object sender, EventArgs e) { try { if (DropDownList4.SelectedIndex > 0) { // 存储选择条件到ViewState,供回发重建使用 ViewState["SelectedProject"] = DropDownList1.SelectedItem.ToString(); ViewState["SelectedScheduleCond"] = DropDownList4.SelectedIndex; // 非回发时首次构建View if (!IsPostBack) { BuildViews(DropDownList1.SelectedItem.ToString()); MultiView1.ActiveViewIndex = MultiView1.Views.Count > 0 ? 0 : -1; } } } catch (Exception ex) { // 建议补充异常日志记录,不要直接吞掉异常 } }
3. 修复按钮点击逻辑
protected void Button3_Click(object sender, EventArgs e) { if (MultiView1.ActiveViewIndex > 0) { MultiView1.ActiveViewIndex -= 1; } } protected void Button4_Click(object sender, EventArgs e) { if (MultiView1.ActiveViewIndex < MultiView1.Views.Count - 1) { MultiView1.ActiveViewIndex += 1; TextBox2.Text = (MultiView1.ActiveViewIndex + 1).ToString(); } }
可选优化
如果下拉框选择值可能变更,可以给DropDownList4添加SelectedIndexChanged事件,触发时清空旧的View集合,重新构建新的View列表即可。
内容的提问来源于stack exchange,提问作者sonu
相关产品推荐
相关产品推荐

