我想在页面上放一个按钮,点击一下按钮可以生成一个Label和一个Textbox,再点击按钮可以再生成一个Label和一个Textbox。可是,我的程序在点击按钮之后可以生成一个Label和一个Textbox,再点击会替换掉原先生成的,怎么办?我的代码如下:
页面:
<asp:textbox id="txt_count" Runat="server"></asp:textbox>
<asp:panel id="pan_OtherHost" Runat="server"></asp:panel>
<asp:button id="Button1" runat="server" Text="增加"></asp:button>后台:
txt_count的初始值为1;
private void Button1_Click(object sender, System.EventArgs e)
{
i=Convert.ToInt32(this.txt_count.Text);
System.Web.UI.WebControls.Label lab1=new Label();
lab1.ID="lab_Name"+this.txt_count.Text;
lab1.Text="第"+this.txt_count.Text+"个文本框";
System.Web.UI.WebControls.TextBox txt1=new TextBox();
txt1.ID="txt_Name"+this.txt_count.Text;

this.pan_OtherHost.Controls.AddAt(this.pan_OtherHost.Controls.Count,lab1);
this.pan_OtherHost.Controls.AddAt(this.pan_OtherHost.Controls.Count,txt1);
i++;
this.txt_count.Text=i.ToString();
}
我希望的是点击一次生成一个,再点击再生成一个,点击N次生成N个,但是我的这个程序怎么点都生成一个。怎么办?

解决方案 »

  1.   

    把Label和Textbox封装到usercontrol,
    然后每点击一次new一个,再load到页面
      

  2.   

    不知道,你发现没有,动态生成出来的控件是保存不住状态的. 
    以前我就发现过这样的问题,当时好像是搞一个自定义控件( 继承自panel控件 ) ,然后override里面的OnInit事件.好像原因就是panel.controls.Add()出来的动态控件,是在页面呈现之后.
    overriede OnInit的目的,就是要先加载这些控件.
      

  3.   

    我想即使楼主解决了主帖里的问题,如果有你要使用这些动态的控件话,还要解决我说这个问题.
    创建应该是小问题.自己多想想,应该很容易搞定.
    Good luck.
      

  4.   

    是啊,动态生成的控件肯定保存不住状态,页面回发时一切都荡然无存了。呵呵
    解决办法是:
    1、在Button1_Click中,当创建新的按钮和Label后,立即把该按钮和label的名称(或其他自定义的标志信息)保存到ViewState
    2、在页面load中,判断ViewState中的内容,并据此还原创建上次创建过的按钮和lable说白了就是自己来实现状态保持。
      

  5.   

    按我的方案不仅保存住了多次创建的TextBox和label,关键是连他们的事件也都保存下来啦~
    下面是伪代码:
    page_load:
    if viewstate["old"] !=Null then
      string TxtBoxID = viewstate["old"];
       TextBox TxtOld = new TextBox();
       TextBox.id =btnID;
    end ifButton1_Click:
      TextBox Txt1 = new TextBox();
      Txt1.id ="abc";
      viewstate["old"]=Txt1.id;
      

  6.   


    没看明白,能详细点吗?btnID是那来的?
      

  7.   

    看来,这类简单的东西也不得不写个demo实实在在地实现功能,否则总是有一堆猜测中的问题。
      

  8.   

    按照1楼的做法,我写了个demo。我补充了两个功能:1. 可以删除每一行。
    2. 可以移动每一行的位置。这两个功能可以更好地说明这类程序的编写所涉及到的问题。顺便说一下,真正的动态装载控件的程序不太可能在OnInit的时候创建所谓动态控件。因为“动态”功能,所以装载时程序要读取ViewState来决定到底如何装载,同时控件自己也要自动地读取ViewState。如果在一个根本读不到页面状态的OnInit阶段去装载动态控件,感觉就是盲人摸象一样不可能写出完整功能功能的动态装载控件的程序(肯定会抱怨无法获得状态)。下面是demo,一共有三个文件,创建以下三个文件就可以直接运行测试:1. 在App_Code下的文件 IMyLine.csusing System;public interface IMyLine
    {
        int 行号 { get; set; }
        string Text { get; set; }    event EventHandler<EventArgs> Delete;
        event EventHandler<EventArgs> Move;
    }
    2. 如1楼所说的封装组件的文件 MyLine.ascx<%@ Control Language="C#" %>
    <%@ Implements Interface="IMyLine" %><script runat="server">
        public event EventHandler<EventArgs> Delete;
        public event EventHandler<EventArgs> Move;    public int 行号
        {
            get
            {
                object x = ViewState["l_no"];
                return x == null ? 1 : (int)x;
            }
            set
            {
                ViewState["l_no"] = value;
                EnsureChildControls();
                this.Label1.DataBind();
            }
        }    public string Text
        {
            get
            {
                EnsureChildControls();
                return this.TextBox1.Text;
            }
            set
            {
                EnsureChildControls();
                this.TextBox1.Text = value;
            }
        }    protected void Button1_Click(object sender, EventArgs e)
        {
            if (this.Delete != null)
                this.Delete(this, EventArgs.Empty);
        }    protected void Button2_Click(object sender, EventArgs e)
        {
            if (this.Move != null)
                this.Move(this, EventArgs.Empty);
        }
    </script><asp:Label ID="Label1" runat="server" Text='<%# string.Format("第{0}个文本框",this.行号) %>' />
    <asp:TextBox ID="TextBox1" runat="server" />
    <asp:Button ID="Button1" runat="server" Text="删除本行" OnClick="Button1_Click" />
    &nbsp;
    <asp:Button ID="Button2" runat="server" Text="移动位置" OnClick="Button2_Click" />
    <hr />
    3. 测试主页 default.aspx <%@ Page Language="C#" %><%@ Import Namespace="System.Collections.Generic" %><script runat="server">    protected void Button1_Click(object sender, EventArgs e)
        {
            最大行序号++;
            string id = "line" + 最大行序号.ToString();
            IMyLine uc = CreateALine(id);
            uc.Text = this.TextBox1.Text;
            uc.行号 = 最大行序号;
            未删除行的id.Add(id);
            this.TextBox1.Text = string.Empty;
            this.TextBox1.Focus();
        }    protected void Page_Load(object sender, EventArgs e)
        {
            foreach (string id in 未删除行的id)
            {
                IMyLine uc = CreateALine(id);
                uc.Delete += new EventHandler<EventArgs>(uc_Delete);
                uc.Move += new EventHandler<EventArgs>(uc_Move);
            }
        }    void uc_Move(object sender, EventArgs e)
        {
            Control uc = (Control)sender;
            PlaceHolder1.Controls.Remove(uc);
            PlaceHolder1.Controls.AddAt(0, uc);
            未删除行的id.Remove(uc.ID);
            未删除行的id.Insert(0, uc.ID);
        }    void uc_Delete(object sender, EventArgs e)
        {
            Control uc = (Control)sender;
            未删除行的id.Remove(uc.ID);
            this.PlaceHolder1.Controls.Remove(uc);
        }    private IMyLine CreateALine(string id)
        {
            Control uc = this.LoadControl("MyLine.ascx");
            uc.ID = id;
            PlaceHolder1.Controls.Add(uc);
            return (IMyLine)uc;
        }    private int 最大行序号
        {
            get
            {
                object x = ViewState["最大行序号"];
                return x == null ? 0 : (int)x;
            }
            set
            {
                ViewState["最大行序号"] = value;
            }
        }    private List<string> 未删除行的id
        {
            get
            {
                object x = ViewState["行id集合"];
                if (x == null)
                {
                    x = new List<string>();
                    ViewState["行id集合"] = x;
                }
                return (List<string>)x;
            }
        }
    </script><html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
        <hr />
        文本框的初始值:<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" Text="添加到最后" OnClientClick="return abc();"
            OnClick="Button1_Click" />
        <br />
        <br />
        <asp:Button ID="Button2" runat="server" Text="测试页面回发(例如您可以先修改文本框中的内容)" />
        </form>
    </body>
    </html>
    实际上,这中程序更加适合创建一个数据集合(然后放到ViewState或者数据库中持久化),然后仅仅使用一个简单的DataList甚至GridView绑定一下就可以了,要比这里的程序简单许多倍。要多用高级的控件,少写低级的代码。只是为了演示如何设计动态装载的程序设计,我才这样设计。
      

  9.   

    应该删除OnClientClick="return abc();"原来脚本中哦你有一个javascript的一句话Confirm确认功能删掉了(但是复制粘贴到csdn时没有删除这个OnClientClick),有没有这一确认对程序逻辑没有影响。