【问题标题】:ASP.NET Page with multiple custom controls implementing IPostBackEventHandler具有多个实现 IPostBackEventHandler 的自定义控件的 ASP.NET 页面
【发布时间】:2012-10-11 05:19:05
【问题描述】:

我有一个 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;)' />");
    }
}

有 2 个自定义控件 - MyTextBox 和 MyButton 实现 IPostBackEventHandler 接口。 MyTextBox 有 TextChange 事件,MyButton 有 Click 事件。

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

在将其发布到此处之前,我已经尝试了多种方法。提前感谢您的帮助。

【问题讨论】:

    标签: asp.net event-handling postback


    【解决方案1】:

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

    文本框:

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

    按钮:

    output.Write("<input type='button' id='" + this.ClientID + "' name='" + this.UniqueID + "' value='Click Me' onclick='__doPostBack(&#39;" + this.UniqueID + "&#39;,&#39;&#39;)' />");
    

    编辑

    使用 UniqueID 似乎确实无助于解决您的问题。我不知道问题的原因,但我尝试使用基本 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");
        }
    }
    

    【讨论】:

    • 马克西姆,感谢您的回复。我已经尝试使用更新的代码,但我仍然面临同样的问题。如果我在页面上只保留一个控件(MyTextBox 或 MyButton) - 事件触发属性。但是对于页面上的两个控件,即使在单击 MyButton 之后,MyTextBox TextChange 事件也会被触发。当 MyTextBox 在页面上时,不会触发 MyButton Click 事件。
    • @Yuvi,我更新了我的答案。我真的没有找到根本原因(出了什么问题),但我尝试使用 WebControl 作为基类来实现相同的功能,这有助于解决问题。愿您对这个解决方案感兴趣。
    • 感谢您的倡议,非常感谢。我尝试过从 WebControl 继承,它确实有效。但我试图通过从 Control 类继承来实现相同的功能。控件类是您可以开始构建控件的最轻量级。似乎 UniqueID 和 ClientID 在 Control 类级别没有多大意义,它们在 WebControl 级别确实有意义。
    猜你喜欢
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多