No, no se puede hacer esto. El motivo es la encapsulación: los eventos son solo suscribirse/cancelar suscripción, es decir, no permiten "echar un vistazo dentro" para ver qué manejadores ya están suscritos.
Lo que podría hacer es derivar de Button, y crear un método público que llame al OnClick
. Entonces solo necesita hacer btn1
una instancia de esa clase, y suscribir un controlador al btn2
que llama al btn1.RaiseClickEvent()
o lo que sea que llame el método.
No estoy seguro de que realmente lo recomiende. ¿Qué estás tratando de hacer? ¿Cuál es la imagen más grande?
EDIT: Veo que ha aceptado la versión que capta el conjunto actual de eventos con reflejo, pero en caso de que esté interesado en la alternativa que llama al controlador OnXXX en el control original, tengo una muestra aquí. Originalmente copié todos los eventos, pero eso conduce a algunos efectos muy extraños. Tenga en cuenta que esta versión significa que si alguien se suscribe a un evento en el botón original después de llamando a CopyEvents, todavía está "conectado", es decir, no importa cuando se asocian los dos.
using System;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
class Test
{
static void Main()
{
TextBox output = new TextBox
{
Multiline = true,
Height = 350,
Width = 200,
Location = new Point (5, 15)
};
Button original = new Button
{
Text = "Original",
Location = new Point (210, 15)
};
original.Click += Log(output, "Click!");
original.MouseEnter += Log(output, "MouseEnter");
original.MouseLeave += Log(output, "MouseLeave");
Button copyCat = new Button
{
Text = "CopyCat",
Location = new Point (210, 50)
};
CopyEvents(original, copyCat, "Click", "MouseEnter", "MouseLeave");
Form form = new Form
{
Width = 400,
Height = 420,
Controls = { output, original, copyCat }
};
Application.Run(form);
}
private static void CopyEvents(object source, object target, params string[] events)
{
Type sourceType = source.GetType();
Type targetType = target.GetType();
MethodInfo invoker = typeof(MethodAndSource).GetMethod("Invoke");
foreach (String eventName in events)
{
EventInfo sourceEvent = sourceType.GetEvent(eventName);
if (sourceEvent == null)
{
Console.WriteLine("Can't find {0}.{1}", sourceType.Name, eventName);
continue;
}
// Note: we currently assume that all events are compatible with
// EventHandler. This method could do with more error checks...
MethodInfo raiseMethod = sourceType.GetMethod("On"+sourceEvent.Name,
BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic);
if (raiseMethod == null)
{
Console.WriteLine("Can't find {0}.On{1}", sourceType.Name, sourceEvent.Name);
continue;
}
EventInfo targetEvent = targetType.GetEvent(sourceEvent.Name);
if (targetEvent == null)
{
Console.WriteLine("Can't find {0}.{1}", targetType.Name, sourceEvent.Name);
continue;
}
MethodAndSource methodAndSource = new MethodAndSource(raiseMethod, source);
Delegate handler = Delegate.CreateDelegate(sourceEvent.EventHandlerType,
methodAndSource,
invoker);
targetEvent.AddEventHandler(target, handler);
}
}
private static EventHandler Log(TextBox output, string text)
{
return (sender, args) => output.Text += text + "\r\n";
}
private class MethodAndSource
{
private readonly MethodInfo method;
private readonly object source;
internal MethodAndSource(MethodInfo method, object source)
{
this.method = method;
this.source = source;
}
public void Invoke(object sender, EventArgs args)
{
method.Invoke(source, new object[] { args });
}
}
}
EventHandler btnClick = new EventHandler (btn1_Click); btn1.Click - = btnClick; btn2.Click + = btnClick; Si eso no ayuda, no sé si entiendo lo que quiere. – shahkalpesh
Tenga en cuenta que no necesita "nuevo EventHandler (...)" a partir de C# 2 - solo "EventHandler btnClick = btn1_Click" hará ... es muy raro que necesite "nuevo WhateverDelegateType (...)" a partir de C# 2. –
Lo siento, uso mucho los fragmentos nuevos para poder TAB TAB. – MusiGenesis