【问题标题】:Dynamically created cascading dropdown lists动态创建的级联下拉列表
【发布时间】:2018-09-12 20:54:35
【问题描述】:

这个问题对某些人来说可能是微不足道的,但对于我的生活,我似乎无法弄清楚。

设置: 我在设计时添加了一个下拉列表 (DropDownList1)。 DropDownList1 在运行时根据所选值动态创建其他下拉列表(DDL1、DDL2、DDL3)。每次回发都会生成下拉列表项作为默认值。一些动态创建的下拉菜单(DLL2、DDL3)也是级联下拉菜单,其中 DDL3 数据项是根据 DDL2 选定项生成的。我在 DDL2 上有一个 onSelectedIndexChanged 事件来为 DDL3 生成数据项。

问题: DDL1 和 DDL2 选定的值在回发时保留,这是有道理的,因为它是在页面加载时生成的。 DDL3 根据 DDL2 选择显示正确的数据项,但在选择一个值后,页面回发并丢失所选值。

标记:

            <asp:UpdatePanel ID="upanel" runat="server">
                <ContentTemplate>
                    <div class="container1">
                        <div id="params-container" class="container">
                            <asp:DropDownList ID="DropDownList1" runat="server" CssClass="input-fields" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged" AutoPostBack="true"></asp:DropDownList>
                            <asp:PlaceHolder ID="DatesPh" runat="server" EnableViewState="false"></asp:PlaceHolder>
                            <asp:PlaceHolder ID="SeasonPh" runat="server" EnableViewState="false"></asp:PlaceHolder>
                            <asp:PlaceHolder ID="CompanyPh" runat="server" EnableViewState="false"></asp:PlaceHolder>
                            <asp:PlaceHolder ID="BrandPh" runat="server" EnableViewState="false"></asp:PlaceHolder>
                            <asp:PlaceHolder ID="LocationPh" runat="server" EnableViewState="false"></asp:PlaceHolder>
                            <asp:PlaceHolder ID="GenderPh" runat="server" EnableViewState="false"></asp:PlaceHolder>
                            <asp:PlaceHolder ID="LinePh" runat="server" EnableViewState="false"></asp:PlaceHolder>
                            <asp:PlaceHolder ID="SubLinePh" runat="server" EnableViewState="false"></asp:PlaceHolder>
                            <asp:PlaceHolder ID="PlaceHolder1" runat="server" EnableViewState="false"></asp:PlaceHolder>
                            <asp:Button ID="Button1" runat="server" Text="Show" OnClick="Button1_Click" class="input-button" />
                        </div>
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>

代码背后:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        using (SqlConnection cn = new SqlConnection(connStr))
        {
//This is my design time dropdown.
//List item is generated only on first request.
//It has AutoPostBack=true so that new controls will be created based on the selection.

            DropDownList1.DataSource =  GetSqlData("sp_getReports",null);
            DropDownList1.DataTextField = "ReportName";
            DropDownList1.DataValueField = "ReportNum";
            DropDownList1.DataBind();
            DropDownList1.Items.Insert(0, new ListItem("Select a report", ""));
            DropDownList1.SelectedIndex = 0;
        }
    }

//This is where I create all controls dynamically (some tb and some ddl).
//I am also generating the list items for the ddl here dynamically.  
//Everything happens on pageload.

using (SqlConnection con = new SqlConnection(connStr))
{

    using (SqlCommand cmd = new SqlCommand("sp_fieldTableMap", con))
    {
        DataTable dtable = new DataTable();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("@inputRpt", DropDownList1.SelectedValue);
        SqlDataAdapter adp = new SqlDataAdapter(cmd);
        adp.Fill(dtable);

        foreach (DataRow dr in dtable.Rows)
        {
            if (dr["SqlQuery"].ToString().Trim() == "")
            {
                TextBox tb = new TextBox();
                tb.ID = dr["AspId"].ToString().Trim();
                tb.CssClass = "input-fields";
                tb.Attributes.Add("placeholder", dr["FieldName"].ToString().Trim());

                Control chkPh = FindControl(dr["Container"].ToString().Trim());
                if (chkPh is PlaceHolder)
                {
                    PlaceHolder pHolder = chkPh as PlaceHolder;
                    pHolder.Controls.Add(tb);
                }
            }
            else
            {
                DropDownList ddl = new DropDownList();
                ddl.ID = dr["AspId"].ToString().Trim();
                ddl.CssClass = "input-fields";
                ddl.AutoPostBack = true;

//I am dynamically creating the selectedindexchanged event
//for one of my ddl to provide cascading dropdown functionality on another dropdown.
                        if (ddl.ID == "brandCode")
                        {    
                ddl.SelectedIndexChanged += new EventHandler(brandCode_SelectedIndexChanged);
                        }
                        if (ddl.ID == "genderCode")
                        {
                            ddl.SelectedIndexChanged += new EventHandler(genderCode_SelectedIndexChanged);
                        } 
                Control chkPh = FindControl(dr["Container"].ToString().Trim());
                if (chkPh is PlaceHolder)
                {
                    PlaceHolder pHolder = chkPh as PlaceHolder;
                    pHolder.Controls.Add(ddl);
                }

                using (SqlConnection cn = new SqlConnection(connStr))
                {

//As I said, I generate the dropdown data items on pageload

                    DataTable sqlTab = new DataTable();
                    SqlCommand sqlCmd = new SqlCommand(dr["SqlQuery"].ToString().Trim(), cn);
                    sqlCmd.CommandType = CommandType.Text;
                    SqlDataAdapter sqlAdp = new SqlDataAdapter(sqlCmd);
                    sqlAdp.SelectCommand.CommandTimeout = 60;
                    sqlAdp.Fill(sqlTab);
                    ddl.DataSource = sqlTab;

                    ddl.DataTextField = dr["DdlText"].ToString().Trim();
                    ddl.DataValueField = dr["DdlValue"].ToString().Trim();
                    ddl.DataBind();
                    ddl.Items.Insert(0, new ListItem("", ""));

//Chidambaram's modified code added after databind of "DDL3"

                    if (ddl.ID == "genderCode") { ddl.SelectedValue = ddlValue; }

                }
            }
        }
    }
}
}
//End of pageload

public String ddlValue
{
    get
    {
        if (ViewState["ddlValue"] == null)
        {
            ViewState["ddlValue"] = String.Empty;
        }
        return ViewState["ddlValue"].ToString();
    }
    set
    {
        ViewState["ddlValue"] = value;
    }
}


//Also added an event for "DDL3" selectedindex to assign its value to the viewstate

    protected void genderCode_SelectedIndexChanged(object sender, EventArgs e)
    {
        Control chkGender = FindControl("genderCode");
        if (chkGender is DropDownList)
        {
            DropDownList ddlGender = chkGender as DropDownList;
            if (ddlGender.SelectedValue == "-1")
            {

            }
            else
            {
                ddlValue = ddlGender.SelectedValue;
            }
        }
    }


protected void brandCode_SelectedIndexChanged(object sender, EventArgs e)
{

//Cascading Dropdown: This event generates the data item of one dropdown based on its selection.
//This runs successfully, gender dropdown only displays the appropriate items based on the brand dropdown.

    Control chkBrand = FindControl("brandCode");
    if (chkBrand is DropDownList)
    {
        DropDownList ddlBrand = chkBrand as DropDownList;
        if (ddlBrand.SelectedValue == "-1")
        {
        }
        else
        {
            SqlParameter param = new SqlParameter();
            param.ParameterName = "@brandCode";
            param.Value = ddlBrand.SelectedValue;    
            Control chkGender = FindControl("genderCode");
            if (chkGender is DropDownList)
            {
                DropDownList ddlGender = chkGender as DropDownList;
                ddlGender.DataSource = GetSqlData("sp_getGender", param);
                ddlGender.DataBind();
                ddlGender.Items.Insert(0, new ListItem("", ""));
                ddlGender.SelectedIndex = 0;
            }
        }
    }
}

private DataSet GetSqlData(string SpName, SqlParameter SpParam)
{
    SqlConnection con = new SqlConnection(connStr);
    SqlDataAdapter da = new SqlDataAdapter(SpName, con);
    da.SelectCommand.CommandType = CommandType.StoredProcedure;
    if (SpParam != null)
    {
        da.SelectCommand.Parameters.Add(SpParam);
    }
    DataSet DS = new DataSet();
    da.Fill(DS);
    return DS;
}

非常感谢任何帮助。谢谢。

添加了一些 cmets。

【问题讨论】:

  • 如果您在 DDL3 选择上进行回发,只需将选定的 DDL3 数据保存在视图状态中,并在页面加载时使用相同的视图状态值设置为 DDL3。如果值为空,则不分配。
  • 确保页面加载时存在任何动态控件,否则值不会丢失。我猜你正在失去价值,因为你得到了错误的控制。使用将成为下拉列表控件的“发送者”对象,而不是“FindControl”。
  • 感谢您的意见。 @Chidambaram我正在使用asp.net服务器控件,如果我没记错的话,那不是已经在内部支持视图状态了吗?只是一个观察,但我对视图状态的解释可能是错误的。
  • @ATerry 我不确定您所说的“发件人”对象是什么意思。你介意详细说明吗?谢谢。
  • 事件参数'sender'是发送事件的控件。

标签: c# asp.net cascadingdropdown


【解决方案1】:

您可以使用如下视图状态来设置和获取值。一旦使用该值,然后将其设置为空或 null。

 public String ddlValue
    {
        get
        {
            if (ViewState["ddlValue"] == null)
            {
                ViewState["ddlValue"] = String.Empty;
            }
            return ViewState["ddlValue"].ToString();
        }
        set
        {
            ViewState["ddlValue"] = value;
        }
    }

public void Page_Load(object sender, EventArgs e)
{
    if (this.ddlValue!=null)
    {
        //set the value here in ddl
        ddl3.selectedvalue=ddlValue;
    }
}

【讨论】:

  • 为我的无知道歉,但我仍然迷失在网页无状态协议的概念上。根据您的建议和我的理解,我添加了您的 ddlvalue 函数。我从 DDL3 的 selectedindexchanged 中调用了 ddlvalue 并分配了它的 selectedvalue。然后我在控件数据绑定后在页面加载时再次调用 ddlvalue。
  • 最后,我得到一个错误“'genderCode' has a SelectedValue which is invalid because it does not exist in the items list.”如果我在数据绑定之后注释代码,则代码运行相同,即 DDL3 正确生成但不保留该值。
  • 我的问题是,我什么时候使用viewstate并获取DDL3的值?当我在 DDL3_selectedindexchanged 事件中进行调试时,DDL3.selectedvalue 显示 DDL3 为“”。是不是因为 DDL2 重新创建了 DDL3 的数据项?
  • 我没有得到您所面临的问题。您是否能够在选择 ddl2 时加载 ddl3 列表值?在选择 ddl3 时无法保留 ddl3 的价值?如果是这样,那么您可以将上述代码中的 ddlvalue 作为全局值并在选择 ddl3 时设置该值,以便在视图状态中重新确定该值并在页面加载中设置该值。
  • 如果您无法加载 ddl3 列表项,那么我上面的答案不起作用。
猜你喜欢
  • 2018-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多