Desplegando un ChildWindow en objetos Window en Silverlight 5
Posted on : 16-01-2012 | By : Rodrigo | In : Silverlight 5
Tags: silverlight 5
3
Silverlight 5 cuenta con muchas características enfocadas principalmente a la construcción de aplicaciones de negocio, una de ellas es la creación de Ventanas de Sistema.
Sin embargo, si necesitas mostrar un ChildWindow dentro de una ventana creada dinámicamente, el comportamiento que obtendrás tal vez no es el esperado, y es que el ChildWindow se mostrará en la raíz de la aplicación (comunmente MainPage) y no en la ventana nueva en donde estás ejecutando el código.
Por ejemplo, en la siguiente figura la aplicación crea la ventana de la izquierda…
…pero al crear el objeto ChildWindow dentro de la ventana en donde esperas que se despliegue:
Este comportamiento no es el esperado ¿cierto?
En este artículo explicaré cómo puedes obligar que el ChildWindow se dibuje adecuadamente en la ventana que le corresponda.
El proyecto
Iniciaremos creando un nuevo proyecto de Silverlight 5, utilizando la plantilla “Silverlight Application”, y configuraremos el proyecto de Silverlight para que la aplicación pueda ejecutar en Confianza Elevada y fuera del navegador.
Agregaré un nuevo control de usuario llamado WindowContent el cual me servirá para establecerlo como el contenido para el objeto de tipo Window que crearemos. Adicionalmente a esto, agregaré un nuevo ChildWindow llamado ChildWindow1. El contenido del ChildWindow no será importante ya que simplemente nuestro objetivo será abrirlo en una ventana dinámica.
En la siguiente figura podrás observar el proyecto de Silverlight completo![]()
En WindowContent, modificaremos su constructor para poder recibir un objeto de tipo Window. Este objeto lo guardaremos en una variable a nivel de clase llamada window:
Window window; public WindowContent(Window window) { InitializeComponent(); this.window = window; }
Además, agregaremos un botón a WindowContent que nos servirá para desplegar efectivamente el ChildWindow deseado (ChildWindow1). Es aquí en donde está la clave de la solución: el método SetWindow de la clase Popup.
Método Popup.SetWindow()
La clase Popup en Silverlight incluye un nuevo método llamada SetWindow. Este método nos permite establecer la ventana que deseamos que actúe como padre del objeto Popup. Pero ¿de dónde obtenemos en este escenario un objeto Popup?
Resulta que al ejecutar el método Show() del objeto ChildWindow, la propiedad Parent será un objeto de tipo Popup. Debido a esto, podemos obtener una referencia a él y posteriormente utilizar el método SetWindow, pasando como parámetro el objeto Window que obtuvimos anteriormente a través del constructor. El único requisito es que el objeto Popup no esté abierto, por lo que será necesario primero ocultarlo, establecer la ventana y finalmente mostrarlo. El siguiente código muestra el manejador Click del botón:
private void button1_Click(object sender, RoutedEventArgs e) { var cw = new ChildWindow1(); cw.Show(); var popup = cw.Parent as Popup; popup.IsOpen = false; popup.SetWindow(window); popup.IsOpen = true; }
Ahora, en MainPage agregaremos un botón, y en su manejador del evento Click escribiremos el código para crear un nuevo objeto de tipo Window, estableciendo como contenido de esta nueva ventana una nueva instancia de WindowContent. Recuerda que deberemos pasar como parámetro en el constructor el objeto de tipo Window relacionado:
private void button1_Click(object sender, RoutedEventArgs e) { var window = new Window() { Width= 800, Height=500, Title = "Nueva ventana", }; var windowContent = new WindowContent(window); window.Content = windowContent; window.Show(); }
Gracias a esto, la nueva ventana podrá desplegar dentro de ella misma el ChildWindow, tal y como lo muestra la siguiente figura:
Nota: Aun con esta técnica, la raíz visual de la aplicación, es decir, el objeto MainPage será deshabilitado cuando el ChildWindow esté siendo desplegado en la ventana creada dinámicamente. Si en tu aplicación esto resulta inconveniente, tal vez desees manejar el evento IsEnabledChanged y establecer el valor de la propiedad IsEnabled a un valor fijo de true, o basado en alguna otra lógica. El siguiente fragmento de código demuestra esto:
//En MainPage this.IsEnabledChanged += (s, a) => this.IsEnabled = true;
Resumen
Las Ventanas de Sistema en Silverlight 5 sin duda alguna es una de las características más útiles en las aplicaciones de negocio. Sin embargo, al combinarlas con los ChildWindow tienen un comportamiento inesperado, pero gracias al método SetWindow de la clase base Popup, podemos obligar a que los ChildWindow se muestren en la ventana adecuada en nuestras aplicaciones.
Salu2!







Me ha gustado mucho este post, para complementado podrías implementar la interfaz IWindowManager, así al usarlo desde caliburnmicro sería una sola línea.
Otro tema interesante es poder hacer undocking de un panel flotante, que salga a la ventana del sistema. Telerik tiene un control de docking, que solo funciona dentro de la ventana principal.
Hi, what resolved size of ChildWindow Overlay, when this element resizable if changed size of ..Host.Content?
Sorry my english is bad.
Gracias por tus recomendaciones Paulo! Salu2!