2011-10-12 100 views
0

我创建了自定义服务器控件。它看起来不错,呈现的HTML也是它应该的。我最初扩展了ControlContainer,现在它扩展了WebControl(两者的行为都相同)。它有两个属性,ImageUrl和Text。从本质上讲,它将呈现一个带有一个和一个标签的通用HTML标签。ASP.Net自定义服务器控件未触发自定义事件

我的问题是暴露的(通过NamingContainer我beleive)ServerClick事件似乎并没有触发。如果我添加任何ASP按钮(链接,图像或常规)并关联到该Click事件,它会触发,但当然我有额外的渲染内容。它成功运行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(); 
    } 
    } 
} 

这是我的标记。我把这个控件,然后一个常规的ASP:Button。常规按钮的事件受到打击!不是我的。

<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" /> 

这里是呈现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" /> 

我不得不相信我靠近,但只是失去了一些东西。一直在调整它几个小时今天,请帮助!

编辑

感谢@詹姆斯的回答,我所做的只是添加以下上面的例子中的顶部。它做了伎俩,但现在发射两次。不知道为什么?所以这是我目前的问题:

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 ==解决方案

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 
    } 
} 

回答

3

尝试实现IPostBackEventHandler接口:

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

下面是解释的执行情况的文章IPostBackEventHandler界面:
http://msdn.microsoft.com/en-us/library/system.web.ui.ipostbackeventhandler.aspx

编辑

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

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

    public virtual void RaisePostDataChangedEvent() 
    { 

    } 
} 

下面是解释了IPostBackDataHandler接口的实现的文章:
http://msdn.microsoft.com/en-us/library/system.web.ui.ipostbackdatahandler.aspx

+0

对不起,我的意思是'IPostBackEventHandler' –

+0

这样做(大部分) - 现在事件触发两次。看到我的答案在下面,所以我可以发布代码。 – Grandizer

+0

您可能只需要稍微修改一下您的事件处理程序逻辑。你指的是什么答案? –

2

你需要考虑IPostBackEventHandler

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

+0

+1你也应得到upvote。 –