现有数据库表,主要用来描述产品类型,其中有1级类,2级子类,3级子类,等等,总之级数不确定.
  现需要在一个页面中实现动态创建无级DropDownList,页面载入时只有一个DropDownList,显示的内容是1级类的数据,当用户下拉选择DropDownList时,根据用户选择的内容读出属于其的2级子类并同时创建第2个DropDownList,同理,当用户下拉第2个DropDownList时,根据用户选择的内容读出属于其的3级子类并同时创建第3个DropDownList,类推下去.
  但是需要注意的是用户有可能在选择到第4个DropDownList时,发现前面选错了,重新到第1个DropDownList上选择,那么此时需要把2,3,4号DropDownList删除掉并重新根据第1个DropDownList的选择创建第2个DropDownList.依次类推.
  我使用PlaceHolder作为容器存放动态控件
  现在的问题是每当页面被刷新时,PlaceHolder1中以前创建的控件就没有了,也尝试过把PlaceHolder1中的对象保存到Session中,还是不行.
  我的代码如下:public ArrayList array=new ArrayList();
private void Page_Load(object sender, System.EventArgs e)
{
if(!this.IsPostBack)
{

//动态创建DROPDOWNLIST
DropDownList l1=new DropDownList();
l1.ID="bigproducttype"+"0";
l1.AutoPostBack=true;
l1.SelectedIndexChanged+=new EventHandler(l1_SelectedIndexChanged);
l1.Items.Insert(0,"---请选择产品所属类型---");
this.PlaceHolder1.Controls.Add(l1);
string sql="select id,name,pid,isend from ts_productg where pid=(select id from ts_productg where pid=0)";
SqlConnection con=new SqlConnection(this.sqlConnString);
con.Open();
SqlCommand cmd=new SqlCommand(sql,con);
SqlDataReader dr=cmd.ExecuteReader();
while(dr.Read())
{
ListItem i=new ListItem(dr["name"].ToString().Trim(),dr["id"].ToString().Trim());
l1.Items.Add(i);
}
//将动态列表寸如数组
array.Add(l1);
Session["createdcontrol"]=array; ViewState["droplistcount"]=1;
dr.Close();
con.Close();
}
else
{ if(ViewState["droplistcount"]==null || Int32.Parse(ViewState["droplistcount"].ToString().Trim())==0)
{
//动态创建DROPDOWNLIST
DropDownList l1=new DropDownList();
l1.ID="bigproducttype"+"0";
l1.AutoPostBack=true;
l1.SelectedIndexChanged+=new EventHandler(l1_SelectedIndexChanged);
l1.Items.Insert(0,"---请选择产品所属类型---");
this.PlaceHolder1.Controls.Add(l1);
string sql="select id,name,pid,isend from ts_productg where pid=(select id from ts_productg where pid=0)";
SqlConnection con=new SqlConnection(this.sqlConnString);
con.Open();
SqlCommand cmd=new SqlCommand(sql,con);
SqlDataReader dr=cmd.ExecuteReader();
while(dr.Read())
{
ListItem i=new ListItem(dr["name"].ToString().Trim(),dr["id"].ToString().Trim());
l1.Items.Add(i);
}
//将动态列表寸如数组
array.Add(l1);
Session["createdcontrol"]=array; ViewState["droplistcount"]=1;
dr.Close();
con.Close();
}
else
{
for(int i=0;i<this.PlaceHolder1.Controls.Count;i++)
{
this.PlaceHolder1.Controls.RemoveAt(i);
} //重新载入事先保存的已经创建的控件
ArrayList list1=(ArrayList)Session["createdcontrol"];
for(int i=0;i<list1.Count;i++)
{
DropDownList tl=(DropDownList)list1[i];
this.PlaceHolder1.Controls.Add(tl);
}
}
}
}
//动态生成
public void l1_SelectedIndexChanged(object sender, System.EventArgs e)
{
DropDownList l=((DropDownList)sender);

string id=l.ID.Trim(); int index=this.PlaceHolder1.Controls.IndexOf(l);

//删除后面的所有下拉列表
for(int i=index+1;i<this.PlaceHolder1.Controls.Count;i++)
{
this.PlaceHolder1.Controls.RemoveAt(i);
}
//删除保存在数组中的对象
for(int i=index+1;i<this.PlaceHolder1.Controls.Count;i++)
{
ArrayList list=(ArrayList)Session["createdcontrol"];
list.RemoveAt(i);
Session["createdcontrol"]=list;
}
ArrayList a=(ArrayList)Session["createdcontrol"];
ViewState["droplistcount"]=a.Count;//this.PlaceHolder1.Controls.Count; string key=l.SelectedValue.Trim();

string sql="select id,name,pid,isend from ts_productg where pid=(select id from ts_productg where id='"+key+"')";
SqlConnection con=new SqlConnection(this.sqlConnString);
con.Open();
SqlCommand cmd=new SqlCommand(sql,con);
SqlDataReader dr=cmd.ExecuteReader();
bool iscreate=false;
while(dr.Read())
{

if(iscreate==false)
{
iscreate=true;
//还有子类,需要再动态生成下拉列表
int temp=Int32.Parse(ViewState["typeindex"].ToString().Trim());
temp++;
ViewState["typeindex"]=temp.ToString().Trim();
DropDownList l1=new DropDownList();
l1.ID="bigproducttype"+ViewState["typeindex"].ToString().Trim();
l1.AutoPostBack=true;
l1.SelectedIndexChanged+=new EventHandler(l1_SelectedIndexChanged);

this.PlaceHolder1.Controls.Add(l1);

l1.Items.Insert(0,"---请选择产品所属类型---");
}
//DropDownList list=(DropDownList)this.PlaceHolder1.Controls[Int32.Parse(ViewState["typeindex"].ToString().Trim())];
DropDownList list=(DropDownList)this.PlaceHolder1.FindControl("bigproducttype"+ViewState["typeindex"].ToString().Trim());
list.Items.Add(new ListItem(dr["name"].ToString().Trim(),dr["id"].ToString().Trim()));
}
//将动态列表寸如数组
DropDownList l2=(DropDownList)this.PlaceHolder1.FindControl("bigproducttype"+ViewState["typeindex"].ToString().Trim());
this.array=(ArrayList)Session["createdcontrol"];
this.array.Add(l2);
Session["createdcontrol"]=array;
ViewState["droplistcount"]=Int32.Parse(ViewState["droplistcount"].ToString().Trim())+1; dr.Close();
con.Close();

}

解决方案 »

  1.   

    现在的问题是每当页面被刷新时,PlaceHolder1中以前创建的控件就没有了
    ——————————————————————————————————————
    建议你先自己写个简单的控件,例如一个一个按钮负责在页面上动态增加文本框,真正学会写控件,再做你这个。不会跑就想飞,太好高鹜远了。
      

  2.   

    刷新还是POSTBACK?
    刷新不会没 POSTBACK看你代码的话可能会没
      

  3.   

    楼上的,你说的
    例如一个一个按钮负责在页面上动态增加文本框,真正学会写控件,再做你这个。不会跑就想飞,太好高鹜远了
    不需要刷新页不需要postback当然没有这个问题,别以为自己星多就了不起,切
    有本事你把我的问题搞出来
      

  4.   

    你费了那么多csdn空间描述了那么多东西,但是我敢拿头打赌你连我说的那个写控件头3天应该入门的知识都没有。
      

  5.   

    你需要把if(!this.IsPostBack)去掉
    另外DropDownList的声明和添加的顺序需要调整,比如
    DropDownList l1=new DropDownList();
    this.PlaceHolder1.Controls.Add(l1);l1.ID="bigproducttype"+"0";
    l1.AutoPostBack=true;
    l1.SelectedIndexChanged+=new EventHandler(l1_SelectedIndexChanged);
    l1.Items.Insert(0,"---请选择产品所属类型---");
      

  6.   

    因为控件的状态只有在控件经历了LoadViewState之后才会跟踪状态变化,所以你需要先在空间层次中确立DropDownList,然后才可以改变其状态(属性)DropDownList l1=new DropDownList();
    this.PlaceHolder1.Controls.Add(l1);if(!this.IsPostBack)
    {
       l1.ID="bigproducttype"+"0";
       l1.AutoPostBack=true;
       l1.SelectedIndexChanged+=new EventHandler(l1_SelectedIndexChanged);
       l1.Items.Insert(0,"---请选择产品所属类型---");
    }
      

  7.   

    详细信息,参看
    http://www.microsoft.com/china/msdn/library/webservices/asp.net/dnasppDynamicUI.mspx