You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 16:24:03