Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clone Control event handlers at run time?

I want to duplicate a control like a Button, TextBox, etc. But I don't know how I can copy event handler methods (like Click) to the new control.

I have the following code now:

var btn2 = new Button();  
btn2.Text = btn1.Text;
btn2.size = btn1.size;
// ...
btn2.Click ??? btn1.Click

Is there any other way to duplicate a control?

like image 980
mrbm Avatar asked May 19 '11 07:05

mrbm


People also ask

How to copy event handlers from one control to another?

Now, press the button named “Copy event handlers” and enter some text in the textbox labeled Destination. If all goes well, you should see the messages from the event handlers attached to the Source textbox now attached to the Destination textbox. For copying handlers from one control to another, you just need those two lines of code:

Why can't I use event handlers in the same thread?

Sharing the same event handler method shouldn't be a problem - it's the BackgroundWorker which provides the "e" in which you store the result. On the other hand, you are accessing resultArray from multiple threads. That could be causing a problem.

Are all workers sharing the same event handler in Salesforce?

All workers are sharing the same event handler which does same thing only with different argument and result like this:

Is there a way to access events in the control class?

For instance, the property Events is marked as protected in the Control class and there isn't another way to access it (unless you are using extended controls or the like, but this isn’t our case). The current implementation only works with events declared on the Control class.


3 Answers

To clone all events of any WinForms control:

var eventsField = typeof(Component).GetField("events", BindingFlags.NonPublic | BindingFlags.Instance);
var eventHandlerList = eventsField.GetValue(button1);
eventsField.SetValue(button2, eventHandlerList);
like image 90
Alex Aza Avatar answered Oct 08 '22 12:10

Alex Aza


You just need to add the event handler method for the new button control. C# uses the += operator to do this. So you could simply write:

btn2.Click += btn1_Click

Alternatively, a somewhat more powerful approach is to use reflection. Of particular use here would be the EventInfo.AddEventHandler method.

like image 25
Cody Gray Avatar answered Oct 08 '22 10:10

Cody Gray


If you're simply looking to duplicate the HTML element that will eventually render (including attached event handlers), you can use below extension method to output a copy of the HTML.

/// <summary>
/// Render Control to HTML as string
/// </summary>
public static string Render(this System.Web.UI.Control control)
{
    var sb = new StringBuilder();
    System.IO.StringWriter stWriter = new System.IO.StringWriter(sb);
    System.Web.UI.HtmlTextWriter htmlWriter = new System.Web.UI.HtmlTextWriter(stWriter);
    control.RenderControl(htmlWriter);
    return sb.ToString();
}

Then you can use it to out put a copy in the aspx markup like this:

<%= btn1.Render() %>

If you want to modify, say, the text on the copy, you could do a string Replace on the Rendered html, or you could set the Text on the original button, and reset it after the Render call in the asx, i.e.:

<% btn1.Text = "Text for original button"; %>
like image 1
Protector one Avatar answered Oct 08 '22 11:10

Protector one