Asegurando una sola instancia de una forma hija en un MDI

Típico te piden que desean que, en tu aplicación MDI, cada vez que escogen abrir un formulario hijo este se abra en la misma ventana, mas no en ventanas separadas. Es decir, si la forma hija ya está abierta, elegir esa, sino ahí sí abrirla. Bueno, es un requerimiento válido, aunque no necesariamente siempre deba ser así. Dado que me gusta hacer cosas un poco fuera de lo común, en mi aplicación MDI yo no tengo una barra de menús, sino más bien un TreeView desde el cual los usuarios eligen el formulario a abrir. Entonces, lo que yo quisiera poder hacer es esto:  

Private Sub RecursosHumanosTreeView_NodeMouseClick(...) Handles ...
        Select Case e.Node.Name
            Case "Forma1Node"
                MostrarForma("Mi forma 1")
            Case "Forma2Node"
                MostrarForma("Mi forma 2")
            Case "Forma3Node"
                MostrarForma("Mi forma 3")
        End Select
End Sub  

¿Cuál sería la forma ideal de lograr un código así de sencillo? Recuerden que la función MostrarForma() debe instanciar la forma correcta según el parámetro enviado. Eso si es que no está ya abierta, porque en ese caso debe más bien activarla. Dado que estoy usando VB 2005, se me ocurrió sacarle provecho a los nuevos Generics. Así, logré hacer a una pequeña función que me redujo el código de una manera increíble y elegante. Esta es mi pequeña función:  

Private Sub MostrarForma(Of T As {Form, New})()
        For Each formaAbierta As Form In My.Application.OpenForms
            If TypeOf (formaAbierta) Is T Then
                formaAbierta.Activate()
                Exit Sub
            End If
        Next
        Dim forma As New T
        forma.MdiParent = Me
        forma.Show()
End Sub  

Lo interesante aquí, como podrán notar, está en la declaración de la función. Básicamente al decir MostrarForma(Of T...) estoy indicando que el método recibe un parámetro de un tipo T, es decir, un tipo que solo será conocido en tiempo de ejecución. Pero, dado que yo sé de antemano que lo que recibiré será siemrpe un formulario, pues apliqué un constraint que solo permita formas: MostrarForma(Of T As {Form...}). Así mismo, dado que yo sé que, si la forma hija aún no está abierta deberé instanciarla, agrego otro constraint de tipo New. Así, mi declaración quedó: MostrarForma(Of T As {Form, New})().   De allí creo que lo demás es obvio. Simplemente busco de entre todas las formas abiertas si alguna de ellas es del tipo T (el tipo de la forma solicitada). Si es así, pues simplemente la activo. Caso contrario creo una nueva instancia de ella y la muestro. Con esta función lista, la llamada queda entonces así:  

Private Sub RecursosHumanosTreeView_NodeMouseClick(...) Handles ...
        Select Case e.Node.Name
            Case "Forma1Node"
                MostrarForma(Of MiForma1)
            Case "Forma2Node"
                MostrarForma(Of MiForma2)
            Case "Forma3Node"
                MostrarForma(Of MiForma3)
        End Select
End Sub  

¿Simple no? Por supuesto en estas cosas siempre hay una forma más simple de hacerlo. ¿Saben de una mejor forma? Please, ¡háganmela conocer!

Published 04 May 2006 09:48 PM por Julio Casal

Comentarios

Aún no existen comentarios