简体   繁体   English

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

[英]ASP.Net Custom Server Control Not Firing Custom Event

I have created a custom server control. 我创建了一个自定义服务器控件。 It looks great and the rendered HTML is also as it should be. 它看起来很棒,并且呈现的HTML也应该如此。 I initially had it extending the ControlContainer and now it extends the WebControl (both behave the same.) It has two properties, ImageUrl and Text. 最初,我扩展了ControlContainer,现在扩展了WebControl(两者的行为相同。)它具有两个属性,ImageUrl和Text。 Essentially it will render a generic HTML tag with an and tags within it. 本质上,它将呈现一个带有和标记的通用HTML标记。

My problem is that the ServerClick event that is exposed (by NamingContainer I beleive) doesn't seem to fire. 我的问题是公开的ServerClick事件(由我相信的NamingContainer)似乎没有触发。 If I add any of the ASP buttons (Link, Image or regular) and associate to that Click event it fires but of course I have extra rendered content. 如果我添加任何ASP按钮(“链接”,“图像”或常规按钮)并关联到该Click事件,则将触发它,但是当然,我还有其他呈现的内容。 It successfully runs the javascript and does the __dopostback call. 它可以成功运行javascript并执行__dopostback调用。 But it must not see the given control ID or something because the event never gets fired. 但是它不能看到给定的控件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();
    }
    }
}

Here is my markup. 这是我的标记。 I put in this control and then a regular ASP:Button. 我放入此控件,然后放入常规的ASP:Button。 That regular button's event gets hit! 该常规按钮的事件被击中! Not mine. 不是我的。

<ucs:ComboButton ID="btnT4" runat="server" Text="Please" CssClass="PButtonCombo" ImageUrl="~/Styles/icons/edit-find.png" OnSubmit="btnT4_Submit" />
<asp:Button ID="btnT5" runat="server" Text="TEST" onclick="btnT5_Click" UseSubmitBehavior="False" />

And here is the rendered HTML: 这是渲染的HTML:

<button id="MainContent_btnT4" class="PButtonCombo" onclick="javascript:__doPostBack(&#39;ctl00$MainContent$btnT4&#39;,&#39;&#39;)"><img src="../Styles/icons/edit-find.png" alt="Please" /><span>Please</span></button>
<input type="button" name="ctl00$MainContent$btnT5" value="TEST" onclick="javascript:__doPostBack(&#39;ctl00$MainContent$btnT5&#39;,&#39;&#39;)" id="MainContent_btnT5" />

I have to believe I am close but just missing something. 我必须相信我已经接近了,但是只是想念一些东西。 Been tweaking it for hours today, PLEASE HELP! 今天已经调整了几个小时,请帮助!

EDIT : 编辑

Thanks to @James answer, all I did was add the following to the top of the above example. 感谢@James的回答,我所做的就是将以下内容添加到上述示例的顶部。 It did the trick but now fires twice. 它成功了,但现在开火了两次。 Not sure why? 不知道为什么吗? So that is my current question: 这就是我当前的问题:

public class ComboButton : WebControl, IPostBackEventHandler {

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

    [Category("Action")]
    [Description("Raised when the user clicks the button.")]
    public event EventHandler Click;

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

EDIT 2 == SOLUTION 编辑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
  }
}

Try implementing the IPostBackEventHandler interface: 尝试实现IPostBackEventHandler接口:

public class ComboButton : WebControl, IPostBackEventHandler  
{
    public void RaisePostBackEvent(string eventArgument)
    {
        OnSubmit(EventArgs.Empty); 
    }
}

Here's an article that explains the implementation of the IPostBackEventHandler interface: 这是一篇介绍IPostBackEventHandler接口的实现的文章:
http://msdn.microsoft.com/en-us/library/system.web.ui.ipostbackeventhandler.aspx http://msdn.microsoft.com/en-us/library/system.web.ui.ipostbackeventhandler.aspx

EDIT 编辑

If your events are in some way dependent on data, you need to implement the IPostBackDataHandler interface. 如果事件以某种方式依赖于数据,则需要实现IPostBackDataHandler接口。 For example, you would use the IPostBackDataHandler interface to fire the OnTextChanged event of a TextBox: 例如,您将使用IPostBackDataHandler接口来触发TextBox的OnTextChanged事件:

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

    public virtual void RaisePostDataChangedEvent()
    {

    }
}

Here's an article that explains the implementation of the IPostBackDataHandler interface: 这是一篇介绍IPostBackDataHandler接口的实现的文章:
http://msdn.microsoft.com/en-us/library/system.web.ui.ipostbackdatahandler.aspx http://msdn.microsoft.com/en-us/library/system.web.ui.ipostbackdatahandler.aspx

You need to look into IPostBackEventHandler 您需要研究IPostBackEventHandler

If you dont implement this interface in your control ASP.net engine wont forward the events to your control. 如果未在控件中实现此接口,则ASP.net引擎不会将事件转发到控件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM