0

I have a case like below.

protected void Page_Load(object sender, EventArgs e)
{
    if (SomeCheck())
    { 
        // Block all other events from happening
    }
}
protected void Button1_Click(object sender, EventArgs e)
{

}
protected void Button2_Click(object sender, EventArgs e)
{

}
protected void Button3_Click(object sender, EventArgs e)
{

}
//..
//..
// Other Event Handlers
//..
//..

where I have multiple event handlers like Button clicks here (in example above) and have a Page_Load where I want to check something and on basis of that check I want to block other events from happening. How can I do this? Am I using right event here or should I do this check on Pre_render or something else?

UPDATE

I actually want a solution where I won't have to do any extra code or worry about the check every time I add a new event handler checking for bool variable on every event handler will became tough in code maintenance soon.

yogi
  • 19,175
  • 13
  • 62
  • 92
  • Why not just set a bool `shouldDoEvent` and check that in each event handler? – J. Steen Nov 26 '14 at 11:39
  • I want a do and forget solution, Don't want to worry about implementing that check in every event handler that I have or will add in future. – yogi Nov 26 '14 at 11:40
  • @J.Steen How? `asp.net` is stateless! – Bharadwaj Nov 26 '14 at 11:42
  • 1
    you could remove each event handler of the buttons `Button1.onClick -= new EventHandler(Button1_Click);` – Mivaweb Nov 26 '14 at 11:42
  • 1
    Possible duplicate: http://stackoverflow.com/questions/16089800/temporarily-stop-form-events-from-either-being-raised-or-being-handled – Aki Nov 26 '14 at 11:42
  • @Bharadwaj Not for one page execution. The control events fire after the Load event. – J. Steen Nov 26 '14 at 11:43
  • @J.Steen Setting bool each time when Load event calls? – Bharadwaj Nov 26 '14 at 11:45
  • @Aki and all I actually want a solution where I won't have to do any extra code or worry about the check every time I add a new event handler. what you have suggested is good alternative but will add extra things in my worry list and will be tough in maintenance. – yogi Nov 26 '14 at 11:45
  • @Bharadwaj It's pragmatically simple and it's what the code is doing right now anyway, so why not? They need to remove or rebind event handlers on each Load anyway since they will be autowired on every postback. Besides, a simple solution like that isn't what the OP seems to want. =) – J. Steen Nov 26 '14 at 11:45
  • Maybe a dirty trick like throwing a new ThreadAbortException()? If it doesn't happen very often... – rene Nov 26 '14 at 13:03
  • I've updated my answer. Let me know if it fits your needs – faby Nov 26 '14 at 16:00

2 Answers2

1

try this function to remove click handlers from generic button passed as input

private void RemoveClickEvent(Button b)
{
   FieldInfo f1 = typeof(Control).GetField("EventClick", 
   BindingFlags.Static | BindingFlags.NonPublic);
   object obj = f1.GetValue(b);
   PropertyInfo pi = b.GetType().GetProperty("Events",  
   BindingFlags.NonPublic | BindingFlags.Instance);
   EventHandlerList list = (EventHandlerList)pi.GetValue(b, null);
   list.RemoveHandler(obj, list[obj]);
}

this code came from MSDN

update

after googling in differents question I try to make a puzzle for your question:

the logic is : Get all Controls from the page and get its events, for each event destroy it

foreach (var control in this.Page.Form.Controls)
    {
        foreach(var event in control.GetType.GetEvents()){
            ClearEventInvocations(control, evt.Name);
        }
    }

functions

public static void ClearEventInvocations(this object obj, string eventName)
    {
        var fi = obj.GetType().GetEventField(eventName);
        if (fi == null) return;
        fi.SetValue(obj, null);
    }

    private static FieldInfo GetEventField(this Type type, string eventName)
    {
        FieldInfo field = null;
        while (type != null)
        {
            /* Find events defined as field */
            field = type.GetField(eventName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic);
            if (field != null && (field.FieldType == typeof(MulticastDelegate) || field.FieldType.IsSubclassOf(typeof(MulticastDelegate))))
                break;

            /* Find events defined as property { add; remove; } */
            field = type.GetField("EVENT_" + eventName.ToUpper(), BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic);
            if (field != null)
                break;
            type = type.BaseType;
        }
        return field;
    }

the code isn't tested so forgive me if there are some errors. I want to try to give you the right way to solve your problem. One thing that is missing could be the recoursive call to Parents of parents of controls

thanks to this other answer

Community
  • 1
  • 1
faby
  • 7,394
  • 3
  • 27
  • 44
  • that's a nice piece of code but in real case scenario I won't have only buttons in my screen there might be Grids, DropDowns, CheckBoxes etc. etc. Moreover that there might be numerous events too like DataBinding, ItemCommand and so on. – yogi Nov 26 '14 at 11:49
0

Assuming these are all user created events: DropDownLists, Buttons etc. You should change the way you hook up the events, only adding the ones you require.

Remove all of the events e.g. OnClick="clickEventName" from your .aspx page and move them to the code behind.

protected void Page_Load(object sender, EventArgs e)
{
    Button1.Click += Button1_Click;

    if (!SomeCheck())
    { 
        // Only fire Button2 Click if SomeCheck Fails
        Button2.Click += Button2_Click;

    }
}
protected void Button1_Click(object sender, EventArgs e)
{

}
protected void Button2_Click(object sender, EventArgs e)
{

}

I personally find this is the better way of wiring up control events rather using the page.

Callum
  • 869
  • 5
  • 23