0

Let me start with example: I have Form with one button named "btnTest" and added _click event for it.

private void btnTest_Click(object sender, EventArgs e)
        {
            MessageBox.Show("button click");
        }

Now I want to dynamically generate another _click event for this button using Control class and therefore override the existing event_hendler, so my form would look something like this:

 public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Control[] controls = Controls.Find("btnTest", true); //find control by name
        controls[0].Click += Form1_Click; //generate button click
    }

    private void Form1_Click(object sender, EventArgs e)
    {
        MessageBox.Show("control click"); //want to be displayed
    }

    private void btnTest_Click(object sender, EventArgs e)
    {       
        MessageBox.Show("button click");  //don't want to be displayed
    }
}

So my goal is to enable Form1_Click and to ignore btnTest_Click and to do so dynamically in code. Done some research, but couldn't get the answer.

Why am i doing this?

My main goal is to navigate through controls using ENTER keyword instead of TAB, so when I stumble on button I just want to move forward without triggering original event.

Note that btnTest_Click event is triggered before Form1_Click event and also bad solution would be to do something directly inbtnTest_Click because I have limited amount of controls that I want to navigate using ENTER and hat is changeable, so the buttons I want to ignore would be in controls array.

Any suggestion is helpful, thank you for your time.

Djordje
  • 437
  • 1
  • 12
  • 24
  • 1
    I would try to cancel the 13 on keydown event on the button, so click will only trigger when you hit space or click with the mouse or tap. as you surely don't want to make the button unclickable altogether. – Cee McSharpface Feb 14 '18 at 15:32
  • 1
    This is an XY problem. You're set on a weird solution to solve something that does not actually need any enabling and disabling of these functions, just careful calling. Fairly sure you need to go to KeyDown for this one. – Nyerguds Feb 14 '18 at 15:34
  • Possible duplicate of [Navigation in Windows Forms using enter key](https://stackoverflow.com/questions/5605561/navigation-in-windows-forms-using-enter-key) – Mark Benningfield Feb 14 '18 at 15:37
  • @dlatikay thank you for suggestion, and you are right about nnot wanting to make button unclickable – Djordje Feb 14 '18 at 15:44
  • @MarkBenningfield thank you , but it is not a duplicate because I am not building navigation from start, i am just fixing exiting problem in code that has already been written – Djordje Feb 14 '18 at 15:47
  • I am thinking a simple solution is to use a boolean flag every time you press the *enter* key. Then in your *btnTest_Click* event you just check if this flag is true. – γηράσκω δ' αεί πολλά διδασκόμε Feb 14 '18 at 19:53
  • @γηράσκωδ'αείπολλάδιδασκόμε thank you for suggestion but that would not work in my case, because i am using multiple buttons and don't know which one will be used, and bad solution would be to check flag in all button clicks – Djordje Feb 15 '18 at 09:39

3 Answers3

2

What do you think about this approach

Control control = Controls.Find("btnTest", true).FirstOrDefault(); //find control by name
if(control != null)
{
  btnTest.Click -= btnTest_Click; //Remove Default Event Handler.
  control.Click += Form1_Click; //generate button click
}
Bhuban Shrestha
  • 1,304
  • 11
  • 27
  • thank you for suggestion but it won't work, I can use `btnTest_Click` ,if somehow i can found that `btnTest_Click` name dynamically then this would work, this would be my logic but it needs to be dynamic, i have found solution and will post and answer, note that i've tried `controls[0].Click+=null; controls[0].Click += Form1_Click;` but it won't work – Djordje Feb 15 '18 at 09:51
1

Try this:

controls[0].Click += Form1_Click;
controls[0].Click -= btnTest_Click;
henoc salinas
  • 1,044
  • 1
  • 9
  • 20
  • can't do it, because it needs to be dynamic, i cant use `btnTest_Click` unless I found control by name like buban proposed – Djordje Feb 15 '18 at 09:33
  • ok, if i understand your objetive, you need navigate with enterKey instead of TabKey, but you have a click event handle, so , i believe you can use PreviewKeyDown event handle and create a flag for detect if Enterkey was pressed, then on the others events validate the flag and execute actions according to the flag's status, please view the example code: – henoc salinas Feb 15 '18 at 15:49
  • this is nice thinking and thank you for your effort, but it won't work for me, it needs to be dynamic, let me try to explain, consider the following scenario: I have 17 buttons for navigation today , so i would neet to go and add this `if (e.KeyCode == Keys.Enter)` in al 17, next day i have different 17 buttons for navigation so I need to do this `if (e.KeyCode == Keys.Enter)` again and delete from first 17. – Djordje Feb 15 '18 at 20:32
  • How generate the 17 buttons? i going to modifly the code on answere, i try add 5 buttons on runtime, and add handle for Preview key press and Form1.Click, check this. – henoc salinas Feb 15 '18 at 21:18
0

After some struggle and research i've managed to find solution. My logic is to remove all event hendlers before controls[0].Click += Form1_Click; and that would be the way to override original event. Tried someting like this

 controls[0].Click += null;
 controls[0].Click += Form1_Click;

but it won't work, so i've found solution based on this answer, and my forum would look like this:

        public Form1()
        {
            InitializeComponent();
            InitializeComponent();
            Control[] controls = Controls.Find("btnTest", true); //find control by name
            Button btn = controls[0] as Button;    //safe cast as Button     
            RemoveClickEvent(btn); 
            controls[0].Click += Form1_Click; //generate button click
        }
        private void Form1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("control click"); 
        }
        private void btnTest_Click(object sender, EventArgs e)
        {
            MessageBox.Show("button click"); 
        }

        //remove all event hendlers for button 
        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]);
        }
Djordje
  • 437
  • 1
  • 12
  • 24
  • this solution works but has one not so small issue, because click event is removed, button loses its functionality , so mouse click won't work. – Djordje Feb 15 '18 at 20:26