Pregunta

Me he arrinconado aquí.

Tengo una serie de UserControls que heredan de un padre, que contiene un par de métodos y eventos para simplificar las cosas para no tener que escribir líneas y líneas de código casi idéntico.Como tu lo haces.El padre no contiene otros controles.

Lo que quiero hacer es simplemente tener un controlador de eventos, en el control de usuario principal, que vaya y haga cosas que solo el control principal puede hacer (es decir, llamar condicionalmente a un evento, tal como el evento está definido en el control principal).Luego conectaría este controlador de eventos a todos mis cuadros de entrada en mis controles secundarios, y los controles secundarios resolverían la tarea de analizar la entrada y decirle al control principal si lanzar ese evento.Agradable y limpio, sin código repetitivo de copiar y pegar (lo cual para mí siempre resulta en un error).

Aquí está mi pregunta.Visual Studio cree que estoy siendo demasiado inteligente a la mitad, y me advierte que "el método 'apropiado para el control' [el controlador de eventos en el padre] no puede ser el método para un evento porque una clase de esta clase se deriva ya define el método". Sí, Visual Studio, ese es el punto.I desear tener un controlador de eventos que solo maneje eventos lanzados por clases secundarias, y su único trabajo es permitirme conectar a los hijos sin tener que escribir una sola línea de código.No necesito esos controladores adicionales: toda la funcionalidad que necesito se llama naturalmente a medida que los niños procesan la entrada del usuario.

No estoy seguro de por qué Visual Studio comenzó a quejarse de esto ahora (ya que me permitía hacerlo antes) y no estoy seguro de cómo hacer que desaparezca.Preferiblemente, me gustaría hacerlo sin tener que definir un método que simplemente llame a CheckReadiness.¿Qué está causando esta advertencia, qué está causando que aparezca ahora cuando no apareció hace una hora y cómo puedo hacer que desaparezca sin recurrir a crear pequeños controladores en todas las clases infantiles?

¿Fue útil?

Solución

Declare virtual el método principal, anúlelo en las clases secundarias y llame

base.checkReadyness(sender, e);

(o su eliminación) desde dentro de la clase secundaria.Esto permite una evolución futura del diseño, por ejemplo, si desea realizar algún código de verificación de errores específico antes de llamar al controlador de eventos principal.Es posible que no necesite escribir millones de controladores de eventos como este para cada control, simplemente puede escribir uno y conectar todos los controles a este controlador de eventos que a su vez llama al controlador de eventos principal.

Una cosa que he notado es que si todo este código se coloca dentro de una DLL, es posible que experimente un impacto en el rendimiento al intentar llamar a un controlador de eventos desde una DLL.

Otros consejos

También me acabo de encontrar con este, estoy de acuerdo en que parece que estás haciendo todo correctamente.Declarar el método virtual es, en el mejor de los casos, una solución alternativa, no una solución.

Lo que se está haciendo es válido: un control que sólo existe en la clase derivada y la clase derivada adjunta un controlador de eventos a uno de los eventos de ese control.El hecho de que el método que maneja el evento esté definido en la clase base no está ni aquí ni allá, está disponible en el punto de vinculación al evento.El evento no se adjunta dos veces ni nada tonto por el estilo, es simplemente una cuestión de dónde está definido el método que maneja el evento.

Definitivamente no es un método virtual; no quiero que una clase derivada pueda anular el método.Muy frustrante y, en mi opinión, un error en dev-studio.

Yo también experimenté este problema porque en versiones anteriores de VS, se podían "heredar" los controladores de eventos.Entonces, la solución que encontré sin tener que anular métodos es simplemente asignar el controlador de eventos en algún lugar de la fase de inicialización del formulario.En mi caso, hecho en el constructor (estoy seguro de que OnLoad() también funcionaría):

    public MyForm()
    {
        InitializeComponent();
        btnOK.Click += Ok_Click;
    }

... donde reside el controlador Ok_Click en el formulario base.Comida para el pensamiento.

Me acabo de encontrar con el problema exacto que Merus planteó por primera vez y, al igual que otros que publicaron respuestas, no tengo del todo claro por qué VS (ahora estoy usando Visual C# 2010 Express) se opone a tener el controlador de eventos definido en la base. clase.La razón por la que estoy publicando una respuesta es que en el proceso de solucionar el problema haciendo que el código de la clase base sea un método protegido que las clases derivadas simplemente invocan en sus controladores de eventos (esencialmente vacíos), hice una refactorización y cambio de nombre de la base. método de clase y noté que el diseñador de VS dejó de quejarse.Es decir, cambió el nombre del registro del controlador de eventos (por lo que ya no siguió la convención del diseñador VS de nombrar controladores de eventos con ControlName_EventName), y eso pareció satisfacerlo.Cuando intenté registrar el controlador de eventos base (ahora renombrado) contra los controles de clases derivadas ingresando el nombre en el evento VS apropiado, el diseñador creó un nuevo controlador de eventos en la clase derivada que luego eliminé, dejando el control de clases derivadas registrado. al método de la clase base (controlador de eventos).Net, como era de esperar, C# considera legítimo lo que queremos hacer.Sólo al diseñador de VS no le gusta que sigas la convención de nomenclatura del controlador de eventos del diseñador.No veo la necesidad de que el diseñador trabaje de esa manera.De todos modos, es hora de continuar.

Si su evento ya está definido en su clase principal, no necesita volver a cablearlo en su clase secundaria.Eso hará que el evento se active dos veces.

Verifique si esto es lo que está sucediendo.HTH :)

Este artículo sobre MSDN debería ser un buen punto de partida: Anulación de controladores de eventos con Visual Basic .NET.Échale un vistazo al Cómo la cláusula Handles puede causar problemas en la clase derivada sección.

¿Por qué no declarar el método como virtual en la clase principal y luego anularlo en las clases derivadas para agregar funcionalidad adicional?

Olvídese de que es un controlador de eventos y simplemente anule el método normal adecuado en la clase secundaria.

Esto es lo que hice para llamar a los métodos base en varias formas similares, cada una de las cuales tiene algunas características adicionales a las comunes:

        protected override void OnLoad(EventArgs e)
    {
        try
        {
            this.SuspendLayout();
            base.OnLoad(e);

            foreach (Control ctrl in Controls)
            {
                Button btn = ctrl as Button;
                if (btn == null) continue;

                if (string.Equals(btn.Name, "btnAdd", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnAdd_Click);
                else if (string.Equals(btn.Name, "btnEdit", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnEdit_Click);
                else if (string.Equals(btn.Name, "btnDelete", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnDelete_Click);
                else if (string.Equals(btn.Name, "btnPrint", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnPrint_Click);
                else if (string.Equals(btn.Name, "btnExport", StringComparison.Ordinal))
                    btn.Click += new EventHandler(btnExport_Click);
            }

La posibilidad de omitir el uso del nombre del botón fijo correcto me parece la misma que la posibilidad de no cablear manualmente el controlador heredado.

Tenga en cuenta que es posible que deba probar this.DesignMode para omitir el código en VS Designer, pero funciona bien para mí incluso sin la verificación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top