Reputation: 1297
I am trying to create an extension method Clone() for a RichTextBox (RTB).
I want to set the TextChanged event handler of the new RTB to the TextChanged event handler of the old RTB. For example:
newRTB.TextChanged += oldRTB.TextChanged;
However, the following error is given:
"The event 'System.Windows.Forms.Control.TextChanged' can only appear on the left hand side of += or -=."
One possible solution is to add the event handler as a parameter to the clone method and just recreate the event, but I need to do this for multiple events and that would get cumbersome. Any ideas?
The "=" sign also does not seem to work.
Upvotes: 0
Views: 2228
Reputation: 2520
We could copy the events via reflection
. Now i myself would be wary of doing this, so please test exhaustively and with all versions (2.0, 3.0, 4.0). I tried many ways but the following was the only way, i got it to work. A Smoke test was run on .NET 4.0.
Create an extension method on the Form Class
public static class FormExtension
{
public static void CopyEvent(this Form form, Control src, string fieldName, string eventName, Control dest)
{
EventHandlerList events = (EventHandlerList)typeof(Control)
.GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(src, null);
object key = typeof(Control).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
EventInfo evInfo = typeof(Control).GetEvent(eventName, BindingFlags.Public | BindingFlags.Instance);
Delegate del = events[key];
if (del != null)
{
Delegate d = Delegate.CreateDelegate(evInfo.EventHandlerType, form, del.Method);
MethodInfo addHandler = evInfo.GetAddMethod();
Object[] addHandlerArgs = { d };
addHandler.Invoke(dest, addHandlerArgs);
}
}
}
Now use it like this
Here i show an example of copying the click
and the text changed
event.
this.CopyEvent(richTextBox1, "EventText", "TextChanged", richTextBox2);
this.CopyEvent(richTextBox1, "EventClick", "Click", richTextBox2);
How to use it for other events
You would have to open the Control
class via Reflector and get the field
and the eventnames
.
So in the case of Text Changed
it was something like:
public event EventHandler TextChanged <-----The Event name for the "CopyEvent" function
{
add
{
base.Events.AddHandler(EventText, value);
}
remove
{
base.Events.RemoveHandler(EventText, value);
}
}
where EventText
is
private static readonly object EventText = new object(); <-------The Field name
Upvotes: 2
Reputation: 7963
If you precreate the TextChanged event, you can do this, in a form put two TextBox and a Button, this will make your controls share the event.
private void button1_Click(object sender, EventArgs e)
{
textBox2.TextChanged += new EventHandler(textbox1_TextChanged);
}
private void textbox1_TextChanged(object sender, EventArgs e)
{
MessageBox.Show("this");
}
UPDATE
in a different file, create the method you want, you can take the code of the current event and copy in this method, then you just assign it to the new controls
void MyCloned_TextChanged(object sender, EventArgs e)
{
// Shared method OldRTB to share with NewRTB
}
In the form you will use it like this
public Form1()
{
InitializeComponent();
textBox1.TextChanged += new EventHandler(MyCloned_TextChanged);
textBox2.TextChanged += new EventHandler(MyCloned_TextChanged);
}
Upvotes: 0
Reputation: 1250
Try this:
newRTB.TextChanged += new TextChangedEventHandler(oldRTB_textChanged);
Create a method like this:
void oldRTB_textChanged(object sender, EventArgs e)
{
// do something
}
Upvotes: 0