Inline:
Also, the ImageButton implements both IPostBackEventHandler *and*
IPostBackDataHandler, and so it wouldnt be successful anyway (as you
can see by a close inspection of the code above)
It was with v1.x that if control implemented both IPostBAckEventHandler
and IPostBackDataHandler, IPostBackDataHandler implementation was the one
getting called and IPostBackEventHandler wasn't. Therefore this type of
control would need to call Page.RegisterRequiresRaiseEvent like
ImageButton does in its LoadPostData method (IPostBackDataHandler
implementation). However, I think it should work with v2.x already, at
least with some of my experimenting it did but based on reflected code it
seems to be like in v.1.x. And ImageButton's implementation supports that
view.
Here is the code I'm talking about for
Page.RegisterRequiresRaiseEvent():
...
It seems that if you simply called
Page.RegisterRequiresRaiseEvent(this) sometime in your composite
control that would work fine.
I'm not sure why they did it this way. Its also possible my analysis
may be wrong. Can Teemu shed some more light on this?
Exaclty because RegisterRaiseEvent is used when control itself cannot
raise the event (or better said page framework cannot) one reason being
dual implementation of interfaces or when the control itself isn't source
of the event. If you have CompositeControl with ImageButton as child
control and when you click the ImageButton, your composite control's
IPostBackEventHandler implementation won't be called. ImageButton's will
be, because it was the control responsible for the postback.
Implementing IPostBackEventHandler in custom control would make sense only
when control itself will be the source of the event. Basically you could
just wire handler for the Click event internally in the control and then
raise a new top-level event with no interface implementation.
Based on previous discussion I wrote a couple of implementations with
Button and ImageButton as child control.
'ButtonCompositeControl.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
/// <summary>
/// Summary description for ButtonCompositeControl
/// </summary>
namespace Samples
{
public class ButtonCompositeControl : CompositeControl
{
protected override void CreateChildControls()
{
Button btn = new Button();
btn.ID = "Button1";
btn.Text = "Click me, I'm a Button";
btn.Click += new EventHandler(btn_Click);
Controls.Add(btn);
}
void btn_Click(object sender, EventArgs e)
{
OnButtonClick(e);
}
#region "Event implementation"
private static readonly object EventButtonClick = new object();
public event EventHandler ButtonClick
{
add
{
Events.AddHandler(EventButtonClick, value);
}
remove
{
Events.RemoveHandler(EventButtonClick, value);
}
}
protected virtual void OnButtonClick(EventArgs e)
{
EventHandler eh = Events[EventButtonClick] as EventHandler;
if (eh != null)
{
eh(this, e);
}
}
#endregion
}
}
'ImageButtonCompositeControl.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
/// <summary>
/// Summary description for ButtonCompositeControl
/// </summary>
namespace Samples
{
public class ImageButtonCompositeControl : CompositeControl
{
protected override void CreateChildControls()
{
ImageButton imgbtn = new ImageButton();
imgbtn.ID = "ImageButton1";
imgbtn.AlternateText = "Click me, I'm an ImageButton";
imgbtn.Click += new ImageClickEventHandler(imgbtn_Click);
Controls.Add(imgbtn);
}
void imgbtn_Click(object sender, ImageClickEventArgs e)
{
OnImageButtonClick(e);
}
#region "Event implementation"
private static readonly object EventImageButtonClick = new
object();
public event ImageClickEventHandler ImageButtonClick
{
add
{
Events.AddHandler(EventImageButtonClick, value);
}
remove
{
Events.RemoveHandler(EventImageButtonClick, value);
}
}
protected virtual void OnImageButtonClick(ImageClickEventArgs e)
{
ImageClickEventHandler iceh = Events[EventImageButtonClick] as
ImageClickEventHandler;
if (iceh != null)
{
iceh(this, e);
}
}
#endregion
}
}
'AND HERE's THE TEST PAGE FOR THEM (CODE FILES IN APP_CODE)
<%@ Page Language="C#" %>
<%@ Register Namespace="Samples" TagPrefix="ss" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Button1_ButtonClick(object sender, EventArgs e)
{
Response.Write("Button1 was clicked");
}
protected void Button2_ImageButtonClick(object sender,
ImageClickEventArgs e)
{
Response.Write("Button2 was clicked");
}
</script>
<html xmlns="
http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<ss:ButtonCompositeControl runat="server" ID="Button1"
OnButtonClick="Button1_ButtonClick" />
<ss:ImageButtonCompositeControl runat="server" ID="Button2"
OnImageButtonClick="Button2_ImageButtonClick" />
</div>
</form>
</body>
</html>
--
Teemu Keiski
ASP.NET MVP, AspInsider
Finland, EU
http://blogs.aspadvice.com/joteke