Динамически создаваемые каскадные выпадающие списки
Эта проблема может быть тривиальной для некоторых, но для жизни я, кажется, не могу понять это.
Настройка: у меня есть раскрывающийся список (DropDownList1), добавленный во время разработки. DropDownList1 динамически создает другие выпадающие списки (DDL1, DDL2, DDL3) во время выполнения на основе выбранного значения. Элементы раскрывающегося списка генерируются каждый постбэк как значения по умолчанию. Некоторые из динамически создаваемых раскрывающихся списков (DLL2, DDL3) также являются каскадными раскрывающимися списками, в которых элементы данных DDL3 генерируются на основе выбранного элемента DDL2. У меня есть событие onSelectedIndexChanged на DDL2 для создания элементов данных для 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;
}
Любая помощь с благодарностью. Благодарю.
Добавил несколько комментариев.
1 ответ
Вы можете использовать viewstate как ниже, чтобы установить и получить значение. как только значение используется, затем установите его пустым или нулевым.
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;
}
}