protected void Page_Load(object sender, EventArgs e)
    {
        ListBox newbox = new ListBox();
        newbox.Items.Add(new ListItem("a"));        //Page.Form.Controls.Add(newbox);
        Controls.Add(newbox);
    }为什么最后一句不行——会提示“类型“ListBox”的控件“ctl01”必须放在具有 runat=server 的窗体标记内。”——,而用被注释掉的那句就可以?

解决方案 »

  1.   

    Page.Form是只不过是Controls里边的一个控件。你需要把控件放在Form里边,而不是它旁边。
      

  2.   

    页面要有<form runat="server"
      

  3.   

    果然可以了。这样的话似乎this和this.Page差不多啊,求教
      

  4.   

    ListBox  不添加到 page里面?
      

  5.   

    this就page嘛,public partial class _Default : System.Web.UI.Page
      

  6.   


    你在页面的代码中,this.Page属性返回的应该就是this。你可以输出表达式“this.Page==this”看看它们是不是指向同一个对象。比如你的代码是写在ascx的代码部分中,那么this跟this.Page就肯定不等了,因为this是当前的用户控件,而this.Page属性则是在运行时去向上(循着Parent属性逐层)一直找到Page。在你的页面代码中,this.Controls中可能包括Title、Head、Form等多个控件。asp.net要求检测许多控件是不是在一个HtmlForm类型的空间中,如果不是就会报异常。
      

  7.   

    要求检测许多控件是不是在一个HtmlForm类型的空间中  -->  要求检测许多控件是不是在一个HtmlForm类型的控件中asp.net会处理Page.Controls集合里边的那个HtmlForm,让它产生正确的action属性,这样才能确保正确地回发。所以需要在回发时继续处理其状态和用户交互的控件,通常都会去在运行时检测自己是否在一个HtmlForm内部。如果我们不小心把一个ListBox放到Form外边,假设asp.net允许其这样写(以前的asp.net1.0甚至可能asp.net1.1就允许这样写),页面回发其Form的action指定的url地址的时候,服务器就得不到ListBox里边的客户端提交数据。因为select并不在form内部。这时候使用asp.net进行的用户就该给微软报产品bug了。
      

  8.   

    另外我刚刚看了一下你贴的代码,其实“动态添加”控件通常是:    protected void Page_Load(object sender, EventArgs e)
        {
            ListBox newbox = new ListBox();
            newbox.ID="myList";
            if(!IsPostback)
            {
                newbox.Items.Add(new ListItem("a"));
            }
            Page.Form.Controls.Add(newbox);
        }也就是说,通常会设置ID属性(因为其在控件树上的相对位置会因为其它动态控件的变化而变化,所以给个ID属性才可靠)。但是除了ID属性为外,几乎就不会重复设置其它属性。因为控件自己会记住状态,即使你添加一个Button来不断回发页面,也不需要在Page_load中重复设置属性,状态不会丢失。
      

  9.   


    真是个好方法!是true,谢谢了。