سؤال

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.

هل كانت مفيدة؟

المحلول

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

نصائح أخرى

Try this:

newRTB.TextChanged  += new TextChangedEventHandler(oldRTB_textChanged);

Create a method like this:

void oldRTB_textChanged(object sender, EventArgs e)
{
   // do something
}

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);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top