Taller Desarrollo de Aplicaciones de Negocio basadas en Silverlight 4

Desde los centros de Excelencia Software hemos publicado el nuevo catálogo de Talleres y Jornadas CES 2º Semestre 2010. Entre los que se encuentra el taller que voy a impartir los próximos 25 y 26 de Octubre. En el realizaré laboratorios centrados en el Desarrollo de Aplicaciones de Negocio basadas en Silverlight 4, Windows Phone 7, Bing Maps, Azure, etc.. Si deseas conocer más detalles sobre dicho taller puedes acceder al mismosdesde aquí.

Por otro lado también se van a desarrollar talleres en los Centros de Excelencia Software Microsoft en colaboración con los profesionales de Plain Concepts. La temática de estos versan sobre tecnologías como ASP.NET, Ajax,MS Dynamics ,Metodologías Ágiles, etc..

Problemas al Implementar un servicio WCF en WP7

Al desarrollar el código del ejemplo del artículo anterior, tuve un problema a la hora de implementar el servicio WCF en mi aplicación WP7. El error que Visual Studio 2010 me mostraba era el siguiente:

“custom tool error failed to generate code for the service reference”, mirando y buscando por la red encontré una solución que propone Michael B McLaughlin desde su blog.

Esencialmente lo que tenemos que hacer es abrir una consola de comando como Administrador. Acceder desde esta a la ruta C:Program Files (x86)Microsoft SDKsWindows Phonev7.0Tools para 64 bit y para 32 bit C:Program Files Microsoft SDKsWindows Phonev7.0Tools. Por último incluimos el nombre de la herramienta que va permitir que el servicio arranque y se comunique con Windows Phone 7, más el enlace del servicio que queremos usar”SlSvcUtil.exe http://localhost:56603/Service1.svc?wsdl

image

Al introducir en la consola de comandos C:Program Files (x86)Microsoft SDKsWindows Phonev7.0ToolsSlSvcUtil.exe http://localhost:56603/Service1.svc?wsdl

image

Se generan los archivos que nos permitirán sin problema alguno, trabaja con el servicio de WCF en los diferentes proyectos de Windows Phone 7 que elaboremos.

Creación y utilización de un servicio WCF en Windows Phone 7

En estos últimos días en los que estado probando las distintas formas de obtener datos desde una fuente (Web Services,WPF, REST, etc..), he creado un servicio de WCF que más tarde he usado en Windows Phone 7.

En este post voy a elaborar un servicio sencillo, en el que el usuario introduzca un nombre en la interfaz de WP7 esta petición es pasada al servicio que obtiene los detalles del contacto(Nombre, Apellido, teléfono,etc..) desde una base de datos (que crearemos para dicho fin). Por últimos estos detalles del contacto, son presentados en la interfaz de usuario de WP7.

Comenzaremos creando una nueva base de datos, para ello utilizaremos en SQL Server Management Studio en mi caso la versión 2008. Realizamos clic con el botón derecho sobre Bases de Datos y seleccionamos la opción Nueva Base de Datos.

image                    image 

 

 

Introducimos el nombre de la base de datos,en mi caso Contactos. Expandimos la tabla recientemente creada y hacemos clic con el botón derecho sobre Tablas, seleccionando Nueva Tabla.

image

Ahora vamos a diseñar los campos de la tabla que tendrán las siguientes características:

IDContacto: nchar(10) clave primeria

Nombre:nchar(50)

Apellidos:nchar(50)

Teléfono:numeric(18, 0) permitir valores nulos

Email:nchar(50) permitir valores nulos

También nombraremos la tabla como DTContactos y rellenamos la tabla con los respectivos datos de los contactos.

image     image    

 

 

 

 

El siguiente paso es la creación del servicio WCF. Para ello abrimos Visual Studio 2010, seleccionamos Archivo->Nuevo Proyecto. En el área de plantillas seleccionamos WCF y elegimos la plantilla  WCF Service Application. Introducimos el nombre y la ubicación del servicio como podemos observar a continuación:

image

Ahora vamos añadir un nuevo elemento que nos va permitir obtener los datos desde la base de datos a través de una clase LINQ. Para ello con el botón derecho sobre el servicio(WcfService) , seleccionamos Añadir->Nuevo elemento. En la ventana emergente seleccionamos la plantilla LINQ to SQL Clasess contenida en la sección Data.

image

Ahora nos situamos en el explorador del servidor de Visual Studio 2010. Si no consiguiéramos ver dicho elemento lo añadiríamos desde el menú Vista->Server Explorer. Desplegamos el explorador del servidor sobre Data Connections presionamos con el botón derecho para seleccionar Añadir Conexión.

image

Al realizar esta acción nos encontraremos con una ventana emergente, donde podremos seleccionar la ubicación de la base de datos creada con anterioridad.

image 

 

 

 

Ahora desplegamos la base de datos Contactos->Tablas y arrastramos la tabla DTContacto encima de la clase de LINQ agregada en el anterior paso.

image

Ahora accedemos a IService1.cs y dejamos dicho elemento del siguiente modo:

 

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.Serialization;
  5. using System.ServiceModel;
  6. using System.ServiceModel.Web;
  7. using System.Text;
  8.  
  9. namespace WcfService
  10. {
  11.     
  12.     [ServiceContract]
  13.     public interface IService1
  14.     {
  15.         [OperationContract]
  16.  
  17.         List<DTContacto> EncontrarContacto(string NombreCT);
  18.     }
  19. }

 

Como podemos observar la Interfaz Iservice1 es el contrato de servicio de WCF en el que hemos declarado una única función que toma una cadena como argumento (Nombre del contacto) y devuelve una lista de tipo DTContacto que es la clase de nuestro modelo de datos.

Ahora accedemos a Service1.svc.cs y dejamos dicho elemento del siguiente modo:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.Serialization;
  5. using System.ServiceModel;
  6. using System.ServiceModel.Web;
  7. using System.Text;
  8.  
  9. namespace WcfService
  10. {
  11.     // NOTE: You can use the “Rename” command on the “Refactor” menu to change the class name “Service1” in code, svc and config file together.
  12.     public class Service1 : IService1
  13.     {
  14.         public List<DTContacto> EncontrarContacto(string NombreCT)
  15.         {
  16.  
  17.             DataClasses1DataContext context = new DataClasses1DataContext();
  18.  
  19.             var res = from r in context.DTContactos where r.Nombre == NombreCT select r;
  20.  
  21.             return res.ToList();
  22.  
  23.         }
  24.     }
  25. }

La clase Service1.svc.cs es el servicio encargado de implementar el contrato de servicio IService1. Dentro de dicha clase hemos definido el método EncontrarContacto. Dentro de este, hemos creado un objeto de contexto de datos, Además de una consulta LINQ que obtiene los datos de la base de datos en función del nombre introducido por el usuario. De este modo nos devuelve una lista de objeto de tipo DTContactos.

Seguidamente nos situamos sobre el servicio Service1.svc con el botón derecho elegimos Ver en el Buscador. De esta forma podremos comprobar el correcto funcionamiento del servicio en el explorador.

image      image

 

Copiaremos la URL del Servicio para utilizarla a la hora de añadir el servicio en Windows Phone 7. El siguiente paso es la creación de una nueva aplicación Windows Phone 7. Para ello en visual estudio elegimos la plantilla Windows Phone Application dentro del área Silverlight For Windows Phone.

image

Comenzamos introduciendo la interfaz de usuario de WP7. Para ello introducimos el siguiente código en MainPage.xaml :

  1. <phone:PhoneApplicationPage
  2.     x:Class=”WindowsPhoneApplication.MainPage”
  3.     xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
  4.     xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
  5.     xmlns:phone=”clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone”
  6.     xmlns:shell=”clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone”
  7.     xmlns:d=”http://schemas.microsoft.com/expression/blend/2008″
  8.     xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006″
  9.     FontFamily=”{StaticResource PhoneFontFamilyNormal}
  10.     FontSize=”{StaticResource PhoneFontSizeNormal}
  11.     Foreground=”{StaticResource PhoneForegroundBrush}
  12.     SupportedOrientations=”Portrait” Orientation=”Portrait”
  13.     mc:Ignorable=”d” d:DesignWidth=”480″ d:DesignHeight=”768″
  14.     shell:SystemTray.IsVisible=”True”>
  15.  
  16.     <!–LayoutRoot contains the root grid where all other page content is placed–>
  17.     <Grid x:Name=”LayoutRoot” Background=”Transparent”>
  18.         <Grid.RowDefinitions>
  19.             <RowDefinition Height=”Auto”/>
  20.             <RowDefinition Height=”*”/>
  21.         </Grid.RowDefinitions>
  22.  
  23.         <!–TitlePanel contains the name of the application and page title–>
  24.         <StackPanel x:Name=”TitlePanel” Grid.Row=”0″ Margin=”24,24,0,12″>
  25.            
  26.             <TextBlock x:Name=”PageTitle” Text=”CONTACTOS” Margin=”-3,-8,0,0″ Style=”{StaticResource PhoneTextTitle1Style}“/>
  27.         </StackPanel>
  28.  
  29.         <!–ContentPanel – place additional content here–>
  30.         <Grid x:Name=”ContentGrid” Grid.Row=”1″>
  31.             <TextBox Height=”79″ HorizontalAlignment=”Left” Margin=”51,218,0,0″ Name=”textBox1″ Text=”” VerticalAlignment=”Top” Width=”401″ />
  32.             <Button Height=”70″ HorizontalAlignment=”Left” Margin=”152,304,0,0″ Name=”button1″ VerticalAlignment=”Top” Width=”160″ Content=”BUSCAR” Click=”button1_Click” />
  33.             <TextBlock Height=”57″ HorizontalAlignment=”Left” Margin=”63,122,0,0″ Name=”textBlock1″ Text=”INTRODUZCA EL NOMBRE DEL CONTACTO A BUSCAR:” VerticalAlignment=”Top” Width=”398″ FontFamily=”Segoe WP Black” TextWrapping=”Wrap” />
  34.         </Grid>
  35.     </Grid>
  36.     
  37.     
  38. </phone:PhoneApplicationPage>

El siguiente paso añadir el servicio al proyecto WP7. Para ello hacemos clic sobre Referencias y seleccionamos Añadir Referencia de Servicio. En la ventana emergente, en el apartado Address introducimos la dirección del servicio que hemos copiado con anterioridad. Presionamos el botón GO para comprobar que se conecta correctamente al servicio. En último lugar nombraremos el espacio de nombres del servicio como ServiceReference como podemos observar a continuación:

image

Ahora vamos añadir una nueva página en el proyecto que mostrará los diferentes detalles del contacto una vez devuelta la petición a la base de datos. Presionamos con el botón derecho sobre el Proyecto(WindowsPhoneApplication), seleccionamos Añadir->Nuevo Elemeto. Seleccionamos la plantilla  Windows Phone Portrait Page como podemos observar en la imagen:

image

Dentro de la interfaz de usuario vamos a incluir un control Listbox, dentro del mismo crearemos una plantilla para incluir los diferentes objetos Texblock que enlazarán con las propiedades del elemento buscado, recuperado de la base de datos. Este es el resultado de la interfaz de usuario de Page1.xaml:

  1. <phone:PhoneApplicationPage
  2.     x:Class=”WindowsPhoneApplication.Page1″
  3.     xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
  4.     xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
  5.     xmlns:phone=”clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone”
  6.     xmlns:shell=”clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone”
  7.     xmlns:d=”http://schemas.microsoft.com/expression/blend/2008″
  8.     xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006″
  9.     FontFamily=”{StaticResource PhoneFontFamilyNormal}
  10.     FontSize=”{StaticResource PhoneFontSizeNormal}
  11.     Foreground=”{StaticResource PhoneForegroundBrush}
  12.     SupportedOrientations=”Portrait” Orientation=”Portrait”
  13.     mc:Ignorable=”d” d:DesignHeight=”768″ d:DesignWidth=”480″
  14.     shell:SystemTray.IsVisible=”True”>
  15.     <phone:PhoneApplicationPage.Resources>
  16.         <Style x:Key=”ListBoxItemStyle1″ TargetType=”ListBoxItem”>
  17.             <Setter Property=”Template”>
  18.                 <Setter.Value>
  19.                     <ControlTemplate TargetType=”ListBoxItem”>
  20.                         <Grid/>
  21.                     </ControlTemplate>
  22.                 </Setter.Value>
  23.             </Setter>
  24.         </Style>
  25.         <ControlTemplate x:Key=”ListBoxControlTemplate1″ TargetType=”ListBox”>
  26.             <Grid/>
  27.         </ControlTemplate>
  28.     </phone:PhoneApplicationPage.Resources>
  29.  
  30.     <!–LayoutRoot contains the root grid where all other page content is placed–>
  31.     <Grid x:Name=”LayoutRoot” Background=”Transparent”>
  32.         <Grid.RowDefinitions>
  33.             <RowDefinition Height=”Auto”/>
  34.             <RowDefinition Height=”*”/>
  35.         </Grid.RowDefinitions>
  36.  
  37.         <!–TitlePanel contains the name of the application and page title–>
  38.         <StackPanel x:Name=”TitlePanel” Grid.Row=”0″ Margin=”24,24,0,12″>
  39.             
  40.             <TextBlock x:Name=”PageTitle” Text=”Detalles Contacto” Margin=”-3,-8,0,0″ Style=”{StaticResource PhoneTextTitle1Style} FontSize=”56″ />
  41.         </StackPanel>
  42.  
  43.         <!–ContentPanel – place additional content here–>
  44.         <Grid x:Name=”ContentGrid” Grid.Row=”1″>
  45.             <ListBox Height=”503″ HorizontalAlignment=”Left” Margin=”20,22,0,0″ Name=”listBox1″ VerticalAlignment=”Top” Width=”434″ >
  46.  
  47.                 <ListBox.ItemTemplate>
  48.  
  49.                     <DataTemplate>
  50.  
  51.                         <StackPanel Orientation=”Vertical”>
  52.                             <TextBlock Text=”Nombre:” Foreground=”#FFFB0000″ FontSize=”29.333″/>
  53.                             <TextBlock Text=”{Binding Nombre} FontSize=”29.333″/>
  54.                             <TextBlock Text=”Apellidos:” FontSize=”29.333″ Foreground=”#FFFD0000″/>
  55.                             <TextBlock Text=”{Binding Apellidos} FontSize=”29.333″/>
  56.                             <TextBlock Text=”Teléfono” FontSize=”29.333″ Foreground=”#FFFE0000″/>
  57.                             <TextBlock Text=”{Binding Teléfono} FontSize=”29.333″/>
  58.                             <TextBlock Text=”Email:” FontSize=”29.333″ Foreground=”Red” />
  59.                             <TextBlock Text=”{Binding Email} FontSize=”29.333″/>
  60.  
  61.                         </StackPanel>
  62.  
  63.                     </DataTemplate>
  64.  
  65.                 </ListBox.ItemTemplate>
  66.  
  67.             </ListBox>
  68.         </Grid>
  69.     </Grid>
  70.  
  71. </phone:PhoneApplicationPage>

 

Seguidamente nos situamos en el evento clic del botón de busqueda, dentro de MainPage.Xaml.cs e introducimos código necesario para enviar a Page1 la cadena que el usuario ha introducido en el control habilitado para tal fin:

  1. private void button1_Click(object sender, RoutedEventArgs e)
  2.         {
  3.             string s = textBox1.Text;
  4.  
  5.             this.Content = new Page1(s);
  6.         }

El siguiente paso es situarnos en Page1.Xaml.cs referenciando el servicio en dicho archivo:

  1. using WindowsPhoneApplication.ServiceReference;

Ahora realizaremos la llamada asincrona al servicio( forma normal de realizar la llamada en Silverlight), para recuperar el dato pedido, pasando al servicio el parámetro del contacto deseado. Una vez que se haya completado la llamada asincrona, el dato del contacto será devuelto e introducido en la interfaz del usuario a través del ListBox.

  1. namespace WindowsPhoneApplication
  2. {
  3.     public partial class Page1 : PhoneApplicationPage
  4.     {
  5.         public Page1(string s)
  6.         {
  7.             InitializeComponent();
  8.             Service1Client proxy = new Service1Client();
  9.  
  10.             proxy.EncontrarContactoCompleted += new EventHandler<EncontrarContactoCompletedEventArgs>(proxy_EncontrarContactoCompleted);
  11.             //controlado del evento de completar la llamada al servicio
  12.  
  13.             proxy.EncontrarContactoAsync(s);
  14.             //llamada al método del servicio de forma asincrona
  15.         }
  16.         void proxy_EncontrarContactoCompleted(object sender, EncontrarContactoCompletedEventArgs e)
  17.         {
  18.             listBox1.ItemsSource = e.Result;//carga datos del contacto en el ListBox
  19.         }
  20.     }
  21. }

Llegados a este punto solo nos queda ejecutar el proyecto, introducir el nombre del contacto a buscar.

image

Obteniendo los detalles del contacto al Instante.

image

Alternativas a Dialog Boxes en WPF y Silverlight

Muchas veces necesitamos abrir una serie de ventanas secundarias, para mostrar un mensaje informativo, un error, etc..Una alternativa es la utilización de los famosos Dialog Boxes, aunque esta opción no es recomendable si la aparición de estos mensajes es muy frecuente. Debido a la limitación de esta funcionalidad en XBAP de WPF y Silverlight, ahora propongo una solución alternativa para cada una de las plataformas nombradas con anterioridad.

Para WPF la alternativa es la inclusión de un objeto PopUP, este aparecerá en la interfaz de Usuario con los elementos que nosotros queramos incluir dentro del mismo. A su vez el resto de la interfaz de Usuario será deshabilitada, de esta forma el usuario se centrará únicamente en el PopUP.

El primer paso es crear el objeto PopUp, incluyendo dentro del mismo los correspondientes elementos:

 

PopUp
  1. <Popup Name=”Dialogo” StaysOpen=”True” Placement=”Center” MaxWidth=”200″>
  2.             <Border>
  3.                 <Border.Background>
  4.                     <LinearGradientBrush>
  5.                         <GradientStop Color=”AliceBlue” Offset=”1″/>
  6.                         <GradientStop Color=”LightBlue” Offset=”0″/>
  7.                     </LinearGradientBrush>
  8.                 </Border.Background>
  9.                 <StackPanel Margin=”5″ Background=”White”>
  10.                     <TextBlock Margin=”10″ TextWrapping=”Wrap”>
  11.                         Introduzca su Nombre de Usuario
  12.                     </TextBlock>
  13.                     <TextBox Name=”txtNombre” Margin=”10″/>
  14.                     <TextBlock Margin=”10″ TextWrapping=”NoWrap”>
  15.                         Introduzca su contraseña
  16.                     </TextBlock>
  17.                     <PasswordBox Name=”pass”></PasswordBox>
  18.                     <StackPanel Orientation=”Horizontal” Margin=”10″>
  19.                         <Button Click=”Button_Click” Padding=”3″ Margin=”0,0,5,0″>Aceptar</Button>
  20.                         <Button Click=”Button_Click_1″ Padding=”3″>Cancelar</Button>
  21.                     </StackPanel>
  22.                 </StackPanel>
  23.             </Border>
  24.         </Popup>

 

Como podemos observar los elementos que están incluidos en el PopUp son realmente sencillos (el grado de complejidad queda de tu mano). Simulamos un formulario de login e incluimos un botón de cancelación y de aceptación de ese Login. Por otro lado podemos ver la utilización de la propiedad StaysOpen que nos proporcionará la visibilidad del objeto al que nos estamos refiriendo, hasta que presionemos sobre alguno de los botones incluidos dentro del mismo.

El resultado de toda la interfaz de usuario es el siguiente:

  1. <Window x:Class=”PopUp.MainWindow”
  2.         xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
  3.         xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
  4.         Title=”MainWindow” Height=”800″ Width=”600″>
  5.     <Grid>
  6.         
  7.         <Popup Name=”Dialogo” StaysOpen=”True” Placement=”Center” MaxWidth=”200″>
  8.             <Border>
  9.                 <Border.Background>
  10.                     <LinearGradientBrush>
  11.                         <GradientStop Color=”AliceBlue” Offset=”1″/>
  12.                         <GradientStop Color=”LightBlue” Offset=”0″/>
  13.                     </LinearGradientBrush>
  14.                 </Border.Background>
  15.                 <StackPanel Margin=”5″ Background=”White”>
  16.                     <TextBlock Margin=”10″ TextWrapping=”Wrap”>
  17.                         Introduzca su Nombre de Usuario
  18.                     </TextBlock>
  19.                     <TextBox Name=”txtNombre” Margin=”10″/>
  20.                     <TextBlock Margin=”10″ TextWrapping=”NoWrap”>
  21.                         Introduzca su contraseña
  22.                     </TextBlock>
  23.                     <PasswordBox Name=”pass”></PasswordBox>
  24.                     <StackPanel Orientation=”Horizontal” Margin=”10″>
  25.                         <Button Name=”Aceptar” Click=”Aceptar_Click” Padding=”3″ Margin=”0,0,5,0″>Aceptar</Button>
  26.                         <Button Name=”Cancelar” Click=”Cancelar_Click” Padding=”3″>Cancelar</Button>
  27.                     </StackPanel>
  28.                 </StackPanel>
  29.             </Border>
  30.         </Popup>
  31.         <TextBlock x:Name=”Inicio” HorizontalAlignment=”Left” Height=”44.4″ Margin=”34.2,48,0,0″ TextWrapping=”Wrap” VerticalAlignment=”Top” Width=”218.4″ FontFamily=”Arial Black” FontSize=”16″ Text=”Acceder a CESNAVARRA”/>
  32.         <Button Content=”Acceder” Name=”acesso” Height=”25.2″ Margin=”276.6,45.177,228.6,0″ VerticalAlignment=”Top” Click=”acesso_Click” />
  33.         <TextBlock x:Name=”Mensaje” HorizontalAlignment=”Left” Height=”45″ Margin=”34.2,92.4,0,0″ TextWrapping=”Wrap” VerticalAlignment=”Top” Width=”194.8″ FontFamily=”Arial Black” Foreground=”Red”/>
  34.     </Grid>
  35. </Window>

image

Ahora vamos a crear en el código Behind las distintas funcionalidades del PopUp , para que este funcione de forma correcta.

Comenzaremos con el evento del botón de acceso a nuestra aplicación, en el incluiremos el siguiente fragmento de código:

  1. private void acesso_Click(object sender, RoutedEventArgs e)
  2.         {
  3.             DesactivarUI();
  4.         }
  5.         private void DesactivarUI()
  6.         {
  7.             MainWindow ventana = new MainWindow();
  8.             ventana.IsEnabled = false;
  9.             this.Background = Brushes.LightGray;
  10.             Dialogo.IsOpen = true;
  11.         }

image

 

 

Como podemos observar hemos desactivado los elementos de la interfaz de usuario que están en segundo plano. Además cambiamos el fondo de estos elemento a gris para mejorar la experiencia de usuario. Por último abrimos el objeto PopUp.

El siguiente paso es incluir el código Behind de los botones del PopUp. Comenzamos con el botón Aceptar:

  1.  
  2. private void Aceptar_Click(object sender, RoutedEventArgs e)
  3. {
  4.     Mensaje.Text = “Bienvenido “ + txtNombre.Text;
  5.     this.Background = null;
  6.     HabilitarUI();
  7. }
  8. private void HabilitarUI()
  9. {
  10.     MainWindow ventana = new MainWindow();
  11.     ventana.IsEnabled = true;
  12.     Dialogo.IsOpen = false;
  13. }

image           image  

Como podemos observar mostraremos en la página principal un mensaje con el nombre de la persona logueada. Además eliminamos el fondo de la misma para que el usuario se entere que se ha logueado (aquí dejen su imaginación volar). Por último cerramos el PopUP y habilitamos la ventana.

En el evento del botón cancelar  introducimos el siguiente código:

  1. private void Cancelar_Click(object sender, RoutedEventArgs e)
  2.         {
  3.             HabilitarUI();
  4.             this.Background = Brushes.White;
  5.         }

Como podemos observar realizamos similares acciones que en el anterior evento para dejar la interfaz de usuario como estaba por defecto.

 

 

 

 

En Silverlight realmente es mucho más sencillo que en WPF, a nuestro proyecto tenemos que añadir un nuevo elemento, eligiendo como plantilla ChildWindow como podemos observar a continuación:

image

Ahora nos encargaremos de añadir las propiedades de la ventana (tamaño, fondo, etc) y los elemento que estarán incluidos en la misma. Para que la ventana aparezca y el resto de la interfaz de usuario este deshabilitada, simplemente tenemos que llamar al método Show desde el nombre del objeto que hace referencia a la ventana emergente como podemos observar a continuación:

nuevoelemento.Show();

La conclusión es que aunque no tengamos la funcionalidad nombrada, podemos utilizar diversos caminos para ofrecer al usuario una mejor experiencia de usuario en la que se centre en lo que realmente es importante en cada momento.

Podeis descargar el ejemplo del artículo aquí