none
Conflicto keydown de la clase y la instancia RRS feed

  • Pregunta

  • Cordial saludo comunidad

    Estoy desarrollando un aplicativo en VS 2017 Community en C#, en el cual cree un clase basada en winform (frrmBase), y cree un formulario que hereda de mi winform modificado (frmCosa).

    En la clase frmBase, escribí código en el evento keydown que atiende una combinación de teclas, por ejemplo ctrl + +,

    En el formulario frmCosa también, escribí código en keydown, que atiende entre otras a la misma combinación de letras ctrl  + +.

    Resulta que cuando en ejecución pulso la combinación de tecas ctrl + +, le ejecutan ambos eventos keydown el de frmBase y el de frmCosa.

    Necesito que cuando la combinación de teclas es atendido por el keydown de frmBase no se ejecute el keydown del frmCosa.

    ya utilice e.Handled = true e igual sigue ejecutando los dos eventos.

    Trate de modificar el e.KeyCode del evento keydown y no resulta por que es de solo letura.

    Trate modificando en el evento keypress y tampoco.

    Agradezco ideas para solucionar esta situación que no sea cambiando la combinación de teclas.

    Atento

    Roberto Ruiz

    martes, 16 de octubre de 2018 15:37

Respuestas

  • El problema es que si conectas el evento en las dos clases (con independencia de que una herede de la otra o no), se conectan los dos manejadores al mismo evento, y el propio evento dispara los dos manejadores (en el orden en el que se conectaron), por lo que nada de lo que hagas en un manejador impide que se dispare el otro. Esto ocurre siempre que conectas mas de un manejador a un evento, con independencia de que los varios manejadores esten todos en la misma clase, o en distintas clases, y sin que influya para nada el hecho de que dichas clases hereden unas de otras.

    Como alternativa, puedes declarar en el formulario base un metodo virtual que se invoque desde el manejador del evento. En el formulario hijo, no conectas el evento, sino que haces un override del metodo virtual. Eso hace que el metodo solo se ejecute una vez. El que se ejecuta es el de la clase hija (el que hizo el override), pero si necesitas ejecutar el de la madre puedes llamar desde ahi a base.nombreDelMetodo.

    martes, 16 de octubre de 2018 16:19
    Moderador
  • No es el caso, yo no conecto eventos, el código cada evento de cada formulario es distinto. sin conexión.

    No, no es cierto. Examina el código que el diseñador de formularios ha escrito por ti dentro del archivo .designer.cs. Ahí está la conexión del evento con la rutina que hace de manejador. En la clase hija, se hereda el mismo evento. Y el código del .designer.cs lo vuelve a conectar, esta vez al otro manejador que has declarado en la clase hija.

    como se entera el frmCosa (instancia) que la combinación de teclas fue o no atendida por el evento de la clase frmBase

    Mmm... Así a bote pronto no se me ocurre ninguna forma "elegante" de hacerlo. Pero no hace falta. Si desde la clase madre usas el manejador del evento para llamar a un método virtual, y el método virtual tiene un override en la clase hija, entonces siempre que se llame a ese override quiere decir que la clase madre disparó el evento. No hace falta detectar si la clase madre lo disparó porque sabes que siempre lo disparó.

    martes, 16 de octubre de 2018 20:33
    Moderador

Todas las respuestas

  • El problema es que si conectas el evento en las dos clases (con independencia de que una herede de la otra o no), se conectan los dos manejadores al mismo evento, y el propio evento dispara los dos manejadores (en el orden en el que se conectaron), por lo que nada de lo que hagas en un manejador impide que se dispare el otro. Esto ocurre siempre que conectas mas de un manejador a un evento, con independencia de que los varios manejadores esten todos en la misma clase, o en distintas clases, y sin que influya para nada el hecho de que dichas clases hereden unas de otras.

    Como alternativa, puedes declarar en el formulario base un metodo virtual que se invoque desde el manejador del evento. En el formulario hijo, no conectas el evento, sino que haces un override del metodo virtual. Eso hace que el metodo solo se ejecute una vez. El que se ejecuta es el de la clase hija (el que hizo el override), pero si necesitas ejecutar el de la madre puedes llamar desde ahi a base.nombreDelMetodo.

    martes, 16 de octubre de 2018 16:19
    Moderador
  • No es el caso, yo no conecto eventos, el código cada evento de cada formulario es distinto. sin conexión.

    La idea es que el frmBase, funcione como una caja negra, haga lo que debe y la instancia no se entere pero si no hace nada pues la instancia si responde con el código asociado al evento correspondiente.

    Interesante lo que escribe en el segundo párrafo, pero como se entera el frmCosa (instancia) que la combinación de teclas fue o no atendida por el evento de la clase frmBase?

    A demás veo otro inconveniente, si hago override del método virtual, que se correría en el evento de la clase frmBase para que solo corra una vez, en ese nivel no hay manera de referenciar los controles de la instancia, lo cual limita las posibilidades del código.


    martes, 16 de octubre de 2018 19:22
  • No es el caso, yo no conecto eventos, el código cada evento de cada formulario es distinto. sin conexión.

    No, no es cierto. Examina el código que el diseñador de formularios ha escrito por ti dentro del archivo .designer.cs. Ahí está la conexión del evento con la rutina que hace de manejador. En la clase hija, se hereda el mismo evento. Y el código del .designer.cs lo vuelve a conectar, esta vez al otro manejador que has declarado en la clase hija.

    como se entera el frmCosa (instancia) que la combinación de teclas fue o no atendida por el evento de la clase frmBase

    Mmm... Así a bote pronto no se me ocurre ninguna forma "elegante" de hacerlo. Pero no hace falta. Si desde la clase madre usas el manejador del evento para llamar a un método virtual, y el método virtual tiene un override en la clase hija, entonces siempre que se llame a ese override quiere decir que la clase madre disparó el evento. No hace falta detectar si la clase madre lo disparó porque sabes que siempre lo disparó.

    martes, 16 de octubre de 2018 20:33
    Moderador
  • Ya entiendi a que se refiere con conectar el evento.

    Pues la verdad, la solución que me plantea no me gusta por que que la idea es que el programador que use la clase base no sepa que hace y como funciona (encapsulamiento).

    Pues yo plantee otra solución que si me funciona pero no me parece elegante: cuando la combinación de teclas es atendida por el keydown de la clase base, modifica un propiedad de la clase base que la instancia puede verificar y si la atendio pues no ejecuta el código.

    Queria ver si encontraba alguien con otra idea que permitiera mantener encapsulado el código y fuera una solución elegante.

    Mucha gracias

    miércoles, 17 de octubre de 2018 15:17