C# ASP.Net自定义服务器控件未触发自定义事件

C# ASP.Net自定义服务器控件未触发自定义事件,c#,event-handling,custom-server-controls,C#,Event Handling,Custom Server Controls,我已经创建了一个自定义服务器控件。它看起来很棒,呈现的HTML也应该如此。我最初让它扩展ControlContainer,现在它扩展WebControl(两者的行为相同)。它有两个属性,ImageUrl和Text。本质上,它将呈现一个通用的HTML标记,其中包含and标记 我的问题是,暴露的ServerClick事件(由NamingContainer公开)似乎没有触发。如果我添加任何ASP按钮(链接、图像或常规)并将其关联到该单击事件,它将触发,但当然我有额外的渲染内容。它成功运行javascr

我已经创建了一个自定义服务器控件。它看起来很棒,呈现的HTML也应该如此。我最初让它扩展ControlContainer,现在它扩展WebControl(两者的行为相同)。它有两个属性,ImageUrl和Text。本质上,它将呈现一个通用的HTML标记,其中包含and标记

我的问题是,暴露的ServerClick事件(由NamingContainer公开)似乎没有触发。如果我添加任何ASP按钮(链接、图像或常规)并将其关联到该单击事件,它将触发,但当然我有额外的渲染内容。它成功运行javascript并执行_dopostback调用。但是它不能看到给定的控件ID或其他东西,因为事件永远不会被触发

using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace PLSO.Info.Web.UI {

[DefaultEvent("Submit")]
[DefaultProperty("Text")]
[ToolboxData("<{0}:ComboButton runat=\"server\"> </{0}:ComboButton>")]
public class ComboButton : WebControl {

    private HtmlImage imageControl;
    private HtmlGenericControl spanControl;

    private static readonly object EventSubmitKey = new object();

    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("")]
    [Description("The text to display on the button.")]
    public string Text {
        get { return ViewState["NewText"] as string; }
        set { ViewState["NewText"] = value; }
    }

    [DefaultValue("")]
    [Bindable(true)]
    [Category("Appearance")]
    [UrlProperty()]
    [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
    public string ImageUrl {
        get {
            EnsureChildControls();
            return this.imageControl.Src;
        }
        set {
            EnsureChildControls();
            this.imageControl.Src = value;
        }
    } // ImageUrl - Property

    public override string CssClass {
        get { return ViewState["CssClass"] as string; }
        set { ViewState["CssClass"] = value; }
    }

    [Category("Action")]
    [Description("Raised when the user clicks the button.")]
    public event EventHandler Submit {
        add { Events.AddHandler(EventSubmitKey, value); }
        remove { Events.RemoveHandler(EventSubmitKey, value); }
    }

    protected virtual void OnSubmit(EventArgs e) {
        EventHandler SubmitHandler = (EventHandler)Events[EventSubmitKey];

        if (SubmitHandler != null)
            SubmitHandler(this, e);
    }

    void ComboButton_Submit(object sender, EventArgs e) {
        OnSubmit(EventArgs.Empty);
    }

    protected override void CreateChildControls() {
        Controls.Clear();

        imageControl = new HtmlImage();
        imageControl.Src = this.ImageUrl;
        imageControl.Alt = this.Text;
        this.Controls.Add(imageControl);

        spanControl = new HtmlGenericControl("span");
        spanControl.InnerText = this.Text;
        this.Controls.Add(spanControl);

        this.Submit += new EventHandler(ComboButton_Submit);

        ChildControlsCreated = true;
    }

    protected override void Render(HtmlTextWriter writer) {
        PostBackOptions pbo = new PostBackOptions(this);

        AddAttributesToRender(writer);
        writer.AddAttribute(HtmlTextWriterAttribute.Class, this.CssClass);
        writer.AddAttribute("onclick", string.Format("javascript:{0}", Page.ClientScript.GetPostBackEventReference(pbo)));
        writer.RenderBeginTag(HtmlTextWriterTag.Button);
        imageControl.RenderControl(writer);
        spanControl.RenderControl(writer);
        writer.RenderEndTag();
    }
    }
}
编辑2==解决方案

using System.ComponentModel;
using System.Drawing.Design;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace PLSO.Info.Web.UI {

[DefaultEvent("Submit")]
[DefaultProperty("Text")]
[ToolboxData("<{0}:ComboButton runat=\"server\"> </{0}:ComboButton>")]
public class ComboButton : Button {

    private HtmlImage imageControl;
    private HtmlGenericControl spanControl;

    [DefaultValue("")]
    [Bindable(true)]
    [Category("Appearance")]
    [UrlProperty()]
    [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
    public string ImageUrl {
        get {
            EnsureChildControls();
            return this.imageControl.Src;
        }
        set {
            EnsureChildControls();
            this.imageControl.Src = value;
        }
    } // ImageUrl - Property

    protected override void CreateChildControls() {
        Controls.Clear();

        imageControl = new HtmlImage();
        imageControl.Src = this.ImageUrl;
        imageControl.Alt = this.Text;
        this.Controls.Add(imageControl);

        spanControl = new HtmlGenericControl("span");
        spanControl.InnerText = this.Text;
        this.Controls.Add(spanControl);

        ChildControlsCreated = true;
    } // CreateChildControls - Method - Override

    protected override void Render(HtmlTextWriter writer) {
        PostBackOptions pbo = new PostBackOptions(this);

        AddAttributesToRender(writer);
        writer.RenderBeginTag(HtmlTextWriterTag.Button);
        imageControl.RenderControl(writer);
        spanControl.RenderControl(writer);
        writer.RenderEndTag();
    } // Render - Event - Override
  }
}
使用System.ComponentModel;
使用系统、绘图、设计;
使用System.Web.UI;
使用System.Web.UI.HTMLControl;
使用System.Web.UI.WebControl;
名称空间PLSO.Info.Web.UI{
[默认事件(“提交”)]
[默认属性(“文本”)]
[ToolboxData(“”)
公共类组合按钮:按钮{
私有图像控制;
私有HtmlGenericControl span控件;
[默认值(“”)
[可装订(真实)]
[类别(“外观”)]
[UrlProperty()]
[编辑器(“System.Web.UI.Design.ImageUrlEditor,System.Design,版本=4.0.0.0,区域性=neutral,PublicKeyToken=b03f5f7f11d50a3a”,类型化(UITypeEditor))]
公共字符串ImageUrl{
得到{
ensureChildControl();
返回this.imageControl.Src;
}
设置{
ensureChildControl();
this.imageControl.Src=值;
}
}//ImageUrl-属性
受保护的覆盖无效CreateChildControls(){
控件。清除();
imageControl=新的HtmlImage();
imageControl.Src=this.ImageUrl;
imageControl.Alt=this.Text;
this.Controls.Add(imageControl);
span控制=新的HtmlGenericControl(“span”);
spanControl.InnerText=此.Text;
this.Controls.Add(spanControl);
ChildControlsCreated=true;
}//CreateChildControls-Method-Override
受保护的覆盖无效渲染(HtmlTextWriter编写器){
PostBackOptions pbo=新的PostBackOptions(此选项);
AddAttributesToRender(编写器);
writer.RenderBeginTag(HtmlTextWriterTag.Button);
imageControl.RenderControl(writer);
spanControl.RenderControl(writer);
writer.renderndtag();
}//Render-Event-Override
}
}

尝试实现
IPostBackEventHandler
接口:

public class ComboButton : WebControl, IPostBackEventHandler  
{
    public void RaisePostBackEvent(string eventArgument)
    {
        OnSubmit(EventArgs.Empty); 
    }
}
这里有一篇文章解释了
IPostBackEventHandler
接口的实现:

编辑

如果事件在某种程度上依赖于数据,则需要实现
IPostBackDataHandler
接口。例如,您可以使用
IPostBackDataHandler
接口触发文本框的
OnTextChanged
事件:

public class ComboButton : WebControl, IPostBackDataHandler  
{
    public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        return true;
    }

    public virtual void RaisePostDataChangedEvent()
    {

    }
}
这里有一篇文章解释了
IPostBackDataHandler
接口的实现:

尝试实现
IPostBackEventHandler
接口:

public class ComboButton : WebControl, IPostBackEventHandler  
{
    public void RaisePostBackEvent(string eventArgument)
    {
        OnSubmit(EventArgs.Empty); 
    }
}
这里有一篇文章解释了
IPostBackEventHandler
接口的实现:

编辑

如果事件在某种程度上依赖于数据,则需要实现
IPostBackDataHandler
接口。例如,您可以使用
IPostBackDataHandler
接口触发文本框的
OnTextChanged
事件:

public class ComboButton : WebControl, IPostBackDataHandler  
{
    public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        return true;
    }

    public virtual void RaisePostDataChangedEvent()
    {

    }
}
这里有一篇文章解释了
IPostBackDataHandler
接口的实现:

您需要查看IPostBackEventHandler


如果您不在控件中实现此接口,ASP.net引擎将不会将事件转发给您的控件。

您需要查看IPostBackEventHandler


如果您不在控件中实现此接口,ASP.net引擎将不会将事件转发给您的控件。

对不起,我的意思是
IPostBackEventHandler
就是这样做的(大部分)-现在事件触发两次。请看下面的答案,这样我就可以发布代码了。您可能只需要稍微修改一下事件处理程序逻辑。你指的是什么答案?我试图把代码放在这些评论中,但它把它当作一个段落,因此阅读起来很痛苦。所以我想如果我能回答(因为我看不到答案),那会有帮助,但那也不是答案。因此,我只是在编辑语句之后编辑了最初的post-see。尝试将
OnSubmit(EventArgs.Empty)
移动到
RaisePostBackEvent
方法,并从
CreateChildControls
方法中删除
OnClick
事件处理程序。对不起,我的意思是
IPostBackEventHandler
-现在事件触发两次。请看下面的答案,这样我就可以发布代码了。您可能只需要稍微修改一下事件处理程序逻辑。你指的是什么答案?我试图把代码放在这些评论中,但它把它当作一个段落,因此阅读起来很痛苦。所以我想如果我能回答(因为我看不到答案),那会有帮助,但那也不是答案。因此,我刚刚编辑了EDIT语句之后的初始post-see。尝试将
OnSubmit(EventArgs.Empty)
移动到
RaisePostBackEvent
方法,并从
CreateChildControls
方法中删除
OnClick
事件处理程序。
public class ComboButton : WebControl, IPostBackDataHandler  
{
    public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        return true;
    }

    public virtual void RaisePostDataChangedEvent()
    {

    }
}