Search code examples
c#asp.neteventspostbackservercontrols

Server control event does not fire correctly


First of all, I found a few similar questions. One of them is here , which does not have correct answer.

I'm writing custom server control, which has Text property and Click event. Everything woks fine (Click event is firing and sender object has correct value), but only if I use it only in one place on the page.

This example works fine (if SimpleControl1.Text has value "First control", in response I'm receiving correct value):

protected void SimpleControl1_Click(object sender, EventArgs e)
    {
        SimpleControl sc = sender as SimpleControl;
        if(sc != null)
        {
            Response.Write(sc.Text);
        }
    }

But if I add second control on the same page (SimpleControl2 with text "Second Control"), my first control's Click event will no longer work:

    protected void SimpleControl2_Click(object sender, EventArgs e)
    {
        SimpleControl sc = sender as SimpleControl;
        if (sc != null)
        {
            Response.Write(sc.Text);
        }
    }

So if I click on first control, I'm receiving "Second control" text.

I think I'm missing something, but I'm not sure what.

How to resolve this problem?

Here is my simple Web control:

public class SimpleControl : WebControl, IPostBackEventHandler
{
    public string Text { get; set; }

    protected override void OnInit(EventArgs e)
    {
        Page.RegisterRequiresRaiseEvent(this);
        Page.RegisterRequiresControlState(this);
        base.OnInit(e);
    }

    private static readonly object EventClick = new object();

    protected virtual void OnClick(EventArgs e)
    {
        EventHandler eventHandler = (EventHandler)Events[SimpleControl.EventClick];
        if (eventHandler != null) { eventHandler(this, e); }
    }

    public event EventHandler Click
    {
        add { Events.AddHandler(EventClick, value); }
        remove { Events.RemoveHandler(EventClick, value); }
    }

    protected override object SaveControlState()
    {
        object state = base.SaveControlState();
        return new object[] { state, Text };
    }

    protected override void LoadControlState(object state)
    {
        object[] states = state as object[];
        if (states != null)
        {
            base.LoadControlState(states[0]);
            Text = (string)states[1];
        }
    }

    protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
    {
        writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
        writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
        writer.AddAttribute(HtmlTextWriterAttribute.Onclick, Page.ClientScript.GetPostBackEventReference(this, "Click"));

        writer.RenderBeginTag("div");
        writer.Write(Text);
        writer.RenderEndTag(); 

        base.RenderContents(writer);
    }

    public void RaisePostBackEvent(string eventArgument)
    {
        this.OnClick(EventArgs.Empty);
    }
}

Edit

markap

<cc1:SimpleControl ID="SimpleControl1" runat="server" 
Text="First control" OnClick="SimpleControl1_Click"  />
<cc1:SimpleControl ID="SimpleControl2" runat="server" 
Text="Second Control" OnClick="SimpleControl2_Click" />

p.s. I also removed Control State support but it didn't fixed the problem.


Solution

  • Remove this line from OnInit:

    Page.RegisterRequiresRaiseEvent(this);
    

    The msdn for this method states:

    Only one server control can be registered per page request.

    http://msdn.microsoft.com/en-us/library/system.web.ui.page.registerrequiresraiseevent.aspx