Usando Reflection para tener una única ventana modal personalizable.

 

Tenemos el siguiente escenario: Una aplicación (en este caso en WPF) que tiene varias ventanas modales. Cada ventana contendrá un UserControl único, que a su vez se construirá mediante una serie de parámetros determinados dependientes de lo que requiera el propio control.

El primer enfoque, que lo podemos  llamar a fuerza bruta, sería crear una ventana por cada control de usuario que tenga. El segundo enfoque, algo más fino, sería crear el UserControl antes de la ventana y ajustarlo mediante una propiedad para que lo cargue en el contenedor que le digamos a la ventana. No es lo más elegante, pero estamos instanciando el UserControl en casos particulares y no es algo muy genérico.

El tercer enfoque, que es el que propongo aquí, sería usar Reflection para que la propia ventana sea quien instancie el UserControl y nosotros sólo nos ocupemos de crear la ventana con los parámetros adecuados. Así no tenemos que estar pendiente de la creación del control en sí, sino simplemente de crear la ventana, decirle qué queremos mostrar y mostrarla al usuario.

Para ello, en primer lugar creamos una ventana en WPF. Luego, en el constructor insertaremos los siguientes parámetros:

– Primero, el tipo del control que se instanciará.

– Y después, un listado de parámetros:

  1. 1:  public ModalPropertyWindow(Type childrenType, params object[] logicObject)
  2.  2:          {
  3.  3:              InitializeComponent();
  4.  4:          }

Luego, lo que tenemos que hacer es instanciar el control que queremos con los parámetros que se requieran. Usaremos Activator.CreateInstance, que creará esa instancia con una serie de parámetros. Internamente recorre esa clase y busca un constructor que tenga la disposición de parámetros que le indicamos. Si no lo encuentra, evidentemente producirá una excepción:

  1. this.stackPanel2.Children.Add(Activator.CreateInstance(childrenType, logicObject) as UIElement);

Nótese que directamente añadimos la instancia creada a un StackPanel.

Por último, sólo tenemos que llamar a la ventana e instanciarla con el control que queramos:

  1. ModalPropertyWindow window = new ModalPropertyWindow(typeof(ClientControl), this.currentCliente, this.loggedUser);
  2. window.ShowDialog();

Y así para todas las ventanas que queramos. En resumen: una única ventana modal, todos los controles que queramos y no nos tenemos que preocupar de instanciar cada uno de forma particular.

3 comentarios en “Usando Reflection para tener una única ventana modal personalizable.”

  1. ¿No probaste usar tipos genéricos? Estaría ver como solucionar el tema de no poder pasar argumentos al contructor cuando creas la instancia del control, pero tendrías la ventaja de poder asegurar en tiempo de compilación que el tipo pasado sea un UserControl.

    Un ejemplo seria:
    public ModalProperty(params object[] logicObject) where T : UIElement

    this.stackPanel2.Children.add(new T());

    var window = new ModalPropertyWindow(parametros);
    window.ShowDialog();

  2. Exacto, para mí era más importante el tema de los argumentos, pero la solución que propones es más elegante en cuanto al tipo genérico. Buen aporte, gracias!

  3. Una posible solución para el caso de los argumentos es crear una interface con un método para los argumentos y después indicar que el tipo genérico deba implementar esa interface. Otro solución similar seria utilizando herencia.

    Por ejemplo:
    interface IParametrosControl {
    void Paramatros(params object[] args);
    }

    public ModalPropertyWindows(params object[] logicObject) where T: IParametrosControl, UIElement, new()

    Y donde se crea la instancia del control seria:

    T control = new T();
    control.Parametros(logicObject);
    this.stackPanel2.Childern.add(control);

    Saludos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *