AutoPostBack不能用于自定义控件

问题描述:

我在ASP.net中创建了一个自定义控件,其中包含一个AutoDownBack设置为true的DropDownList。我还为控件附加了一个事件SelectedIndexChanged,但我发现该事件未被触发。正常的asp.net DropDownList与AutoPostBack设置为true将触发事件。我在VS2010中使用.net 3.5版本。AutoPostBack不能用于自定义控件

这里是我的代码: ServerControl1.cs

[ToolboxData("<{0}:ServerControl2 runat=server></{0}:ServerControl2>")] 
public class ServerControl1 : WebControl 
{ 
    protected DropDownList drplist; 
    protected TextBox tb; 

    protected override void RenderContents(HtmlTextWriter output) 
    { 
     drplist.RenderControl(output); 
     tb.RenderControl(output); 

    } 

    protected override void CreateChildControls() 
    { 
     base.CreateChildControls(); 
     drplist = new DropDownList() { AutoPostBack = true }; 
     drplist.Items.Add("a"); 
     drplist.Items.Add("b"); 
     drplist.Items.Add("c"); 
     drplist.Items.Add("d"); 
     drplist.SelectedIndexChanged += new EventHandler(drplist_SelectedIndexChanged); 
     tb = new TextBox(); 
    } 

    void drplist_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     tb.Text = "even fired";   
    } 
} 

ServerControl1Test:

protected void Page_Load(object sender, EventArgs e) 
    { 
     ServerControl1 ServerControl1 = new ServerControl1(); 
     this.Controls.Add(ServerControl1); 
    } 

谁能告诉我我在这里失踪?

首先,您需要将自定义控件作为页面树的一部分。在这种情况下,ASP.NET将能够找到它们并包含所有必需的脚本(如果有的话)。您无需覆盖RenderContents。只需将您的下拉列表以及文本框添加到Controls集合。

其次,请阅读API referenceCreateChildControls。页面底部有评论指出:

请勿覆盖CreateChildControls

您将遇到一个受伤的世界, 特别是当涉及到订阅子控件事件! 相反,请创建一个名为CreateCustomChildControls的私有方法 。 在那里构建控制树。只需 覆盖OnInit并在那里致电 CreateCustomChildControls从 。

所以你的情况的代码如下所示:

[ToolboxData("<{0}:ServerControl2 runat=server></{0}:ServerControl2>")] 
public class ServerControl1 : WebControl 
{ 
    protected DropDownList drplist; 
    protected TextBox tb; 

    protected override void OnInit(EventArgs e) 
    { 
     base.OnInit(e); 

     CreateCustomChildControls(); 
    } 

    private void CreateCustomChildControls() 
    { 
      drplist = new DropDownList() { AutoPostBack = true }; 

      drplist.Items.Add("a"); 
      drplist.Items.Add("b"); 
      drplist.Items.Add("c"); 
      drplist.Items.Add("d"); 

      drplist.SelectedIndexChanged += new EventHandler(drplist_SelectedIndexChanged); 

      tb = new TextBox(); 

      base.Controls.Add(drplist); 
      base.Controls.Add(tb); 
    } 

    void drplist_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     tb.Text = "even fired"; 
    } 
}