ASP.NET页面,包含多个实现IPostBackEventHandler的自定义控件

ASP.NET页面,包含多个实现IPostBackEventHandler的自定义控件,asp.net,event-handling,postback,Asp.net,Event Handling,Postback,我有一个ASP.Net页面,其中包含多个实现IPostBackEventHandler接口的控件。代码的简化版本如下所示: public partial class WebForm1 : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //Custom Control MyTextBox mytxt = new MyTextBox();

我有一个ASP.Net页面,其中包含多个实现IPostBackEventHandler接口的控件。代码的简化版本如下所示:

public partial class WebForm1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //Custom Control
        MyTextBox mytxt = new MyTextBox();
        mytxt.ID = "mytxt";
        mytxt.TextChange += mytxt_TextChange;
        this.Form.Controls.Add(mytxt);

        //Custom Control
        MyButton mybtn = new MyButton();
        mybtn.ID = "mybtn";
        mybtn.Click += mybtn_Click;
        this.Form.Controls.Add(mybtn);
    }

    void mybtn_Click(object sender, EventArgs e)
    {
        Response.Write("mybtn_Click");
    }

    void mytxt_TextChange(object sender, EventArgs e)
    {
        Response.Write("mytxt_TextChange");
    }
}

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class MyTextBox : Control, IPostBackEventHandler
{
    public event EventHandler TextChange;

    protected virtual void OnTextChange(EventArgs e)
    {
        if (TextChange != null)
        {
            TextChange(this, e);
        }
    }

    public void RaisePostBackEvent(string eventArgument)
    {
        OnTextChange(new EventArgs());
    }

    protected override void Render(HtmlTextWriter output)
    {
        output.Write("<input type='text' id='" + ID + "' name='" + ID + "' onchange='__doPostBack(&#39;" + ID + "&#39;,&#39;&#39;)' />");
    }
}

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class MyButton : Control, IPostBackEventHandler
{
    public event EventHandler Click;

    protected virtual void OnClick(EventArgs e)
    {
        if (Click != null)
        {
            Click(this, e);
        }
    }

    public void RaisePostBackEvent(string eventArgument)
    {
        OnClick(new EventArgs());
    }

    protected override void Render(HtmlTextWriter output)
    {
        output.Write("<input type='button' id='" + ID + "' name='" + ID + "' value='Click Me' onclick='__doPostBack(&#39;" + ID + "&#39;,&#39;&#39;)' />");
    }
}
public分部类WebForm1:System.Web.UI.Page
{
受保护的无效页面加载(对象发送方、事件参数e)
{
//自定义控件
MyTextBox mytxt=新建MyTextBox();
mytxt.ID=“mytxt”;
mytxt.TextChange+=mytxt\u TextChange;
this.Form.Controls.Add(mytxt);
//自定义控件
MyButton mybtn=新建MyButton();
mybtn.ID=“mybtn”;
mybtn.Click+=mybtn\u Click;
this.Form.Controls.Add(mybtn);
}
void mybtn_单击(对象发送方,事件参数e)
{
回复。写(“mybtn_点击”);
}
void mytxt_TextChange(对象发送方,事件参数e)
{
响应。写入(“mytxt_TextChange”);
}
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand,Name=“FullTrust”)]
公共类MyTextBox:控件,IPostBackEventHandler
{
公共事件处理程序文本更改;
受保护的虚拟void OnTextChange(EventArgs e)
{
if(TextChange!=null)
{
TextChange(this,e);
}
}
public void RaisePostBackEvent(string eventArgument)
{
OnTextChange(neweventargs());
}
受保护的覆盖无效渲染(HtmlTextWriter输出)
{
输出。写入(“”);
}
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand,Name=“FullTrust”)]
公共类MyButton:控件,IPostBackEventHandler
{
公共事件事件处理程序单击;
受保护的虚拟void OnClick(EventArgs e)
{
如果(单击!=null)
{
点击(此,e);
}
}
public void RaisePostBackEvent(string eventArgument)
{
OnClick(neweventargs());
}
受保护的覆盖无效渲染(HtmlTextWriter输出)
{
输出。写入(“”);
}
}
有两个自定义控件-MyTextBox和MyButton实现IPostBackEventHandler接口。MyTextBox有TextChange事件,MyButton有Click事件

如果我在页面上只保留一个控件(MyTextBox或MyButton)——events fire属性。但是页面上的两个控件都会触发MyTextBox TextChange事件,即使在单击MyButton之后也是如此。当MyTextBox位于页面上时,不会触发MyButton Click事件


在这里发布之前,我尝试了多种方法。提前感谢您的帮助。

问题的原因是您需要使用控件的唯一ID调用uu doPostBack方法。这是至关重要的。另外,基本上服务器控件将ClientID作为元素的ID,将UniqueID作为元素名。因此,如果将渲染方法更新为以下内容,一切都将正常工作:

文本框:

output.Write("<input type='text' id='" + this.ClientID + "' name='" + this.UniqueID + "' onchange='__doPostBack(&#39;" + this.UniqueID + "&#39;,&#39;&#39;)' />");

问题的原因是您需要使用控件的UniqueID调用_doPostBack方法。这是至关重要的。另外,基本上服务器控件将ClientID作为元素的ID,将UniqueID作为元素名。因此,如果将渲染方法更新为以下内容,一切都将正常工作:

文本框:

output.Write("<input type='text' id='" + this.ClientID + "' name='" + this.UniqueID + "' onchange='__doPostBack(&#39;" + this.UniqueID + "&#39;,&#39;&#39;)' />");

马克西姆,谢谢你的回复。我尝试过更新代码,但仍然面临同样的问题。如果我在页面上只保留一个控件(MyTextBox或MyButton)——events fire属性。但是页面上的两个控件都会触发MyTextBox TextChange事件,即使在单击MyButton之后也是如此。当MyTextBox在页面上时,MyButton Click事件不会被触发。@Yuvi,我更新了我的答案。我确实没有找到根本原因(什么是错误的),但我尝试使用WebControl作为基类实现相同的功能,这有助于解决问题。希望这个解决方案会让您感兴趣。谢谢您的倡议,非常感谢。我尝试过从WebControl继承,它确实有效。但我正试图通过从控件类继承来实现相同的功能。控件类是最轻的,您可以从中开始构建控件。似乎UniqueID和ClientID在控制类级别上没有多大意义,它们在WebControl级别上确实有意义。Maxim,感谢您的回复。我尝试过更新代码,但仍然面临同样的问题。如果我在页面上只保留一个控件(MyTextBox或MyButton)——events fire属性。但是页面上的两个控件都会触发MyTextBox TextChange事件,即使在单击MyButton之后也是如此。当MyTextBox在页面上时,MyButton Click事件不会被触发。@Yuvi,我更新了我的答案。我确实没有找到根本原因(什么是错误的),但我尝试使用WebControl作为基类实现相同的功能,这有助于解决问题。希望这个解决方案会让您感兴趣。谢谢您的倡议,非常感谢。我尝试过从WebControl继承,它确实有效。但我正试图通过从控件类继承来实现相同的功能。控件类是最轻的,您可以从中开始构建控件。似乎UniqueID和ClientID在控件类级别上没有多大意义,它们在WebControl级别上确实有意义。
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class MyTextBox : WebControl, IPostBackEventHandler
{
    public event EventHandler TextChange;

    protected virtual void OnTextChange(EventArgs e)
    {
        if (TextChange != null)
        {
            TextChange(this, e);
        }

    }

    public void RaisePostBackEvent(string eventArgument)
    {
        OnTextChange(new EventArgs());
    }

    protected override HtmlTextWriterTag TagKey
    {
        get
        {
            return HtmlTextWriterTag.Input;
        }
    }

    protected override void AddAttributesToRender(HtmlTextWriter writer)
    {
        base.AddAttributesToRender(writer);
        writer.AddAttribute(HtmlTextWriterAttribute.Onchange, Page.ClientScript.GetPostBackEventReference(this, string.Empty));
        writer.AddAttribute("onkeypress", "if (WebForm_TextBoxKeyHandler(event) == false) return false;");
        writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
    }
}