Mostrar un menú contextual (aplicación para Windows Store)

Pues eso… voy a seguir mostrándote algunas de las cosas que voy aprendiendo mientras voy creando mi primera aplicación para la tienda de Windows. En esta ocasión lo que te voy a explicar es cómo mostrar un menú contextual (por llamarlo de alguna forma) al hacer Click en un botón.

Para mostrar el menú contextual vamos a usar las clases PopupMenu y UICommand que están definidas en el espacio de nombres Windows.UI.Popups, que es el mismo en el que está definida la clase MessageDialog que ya vimos que sirve para mostrar mensaje "al estilo Windows 8".

Seguiremos con el código que vimos por última vez el 7 de diciembre en: Saber cuando la aplicación está en modo Snapped y actuar en consecuencia.

También usaremos el código para actualizar periódicamente el icono de la aplicación que ya vimos en Actualizar cada minuto el icono (tile) de una aplicación de Windows Store hasta la hora indicada, es decir el método asignarTiles, por tanto ese método no te lo mostraré en este artículo, más que nada para no repetir el código.

Lo primero que haremos es añadir un botón a la barra de la aplicación (AppBar) y le asignaremos el siguiente estilo: (el cual guardaremos en el fichero StandardStyles.xaml junto con el de los otros botones)

<Style x:Key="LangAppBarButtonStyle" TargetType="ButtonBase" 
       BasedOn="{StaticResource AppBarButtonStyle}">
    <Setter Property="AutomationProperties.AutomationId" Value="LangAppBarButton"/>
    <Setter Property="AutomationProperties.Name" Value="Idioma"/>
    <Setter Property="Content" Value="&#xE128;"/>
</Style>

Ahora añadimos el código XAML del botón, éste lo pondremos en el segundo StackPanel, es decir, junto con el botón About:

<Button x:Name="buttonLang" Click="buttonLang_Click"
        Style="{StaticResource LangAppBarButtonStyle}" />

Una vez hecho esto, nuestra barra de botones tendrá la apariencia mostrada en la figura 1:

menucontextual_01

Figura 1. La barra de botones de la aplicación reloj

Después de ver la captura sabrás que el nombre del botón es buttonLang y el método del evento Click será: buttonLang_Click.

Veamos el código de ese método de evento, además de otro método que usaremos para saber cuál es el menú elegido (ese código, así como el código para mostrar el menú contextual por medio de la clase PopupMenu está sacado de un ejemplo del SDK de Windows: Context menu sample).

También usaremos una serie de variables para los textos a mostrar en las opciones del menú y otra más para asignarle el valor que corresponda al idioma seleccionado en ese menú contextual.

Lo que no veremos (por ahora) son un par de métodos en los que se asignan las cadenas a los controles con el texto del idioma que hemos elegido, ya que para hacer eso antes tenemos que añadir una serie de recursos con los textos en español e inglés que serán los dos idiomas soportados por esta aplicación.

Lo que me interesa es que sepas cómo mostrar ese menú contextual, cómo interceptar el menú seleccionado y actuar en consecuencia.

En este ejemplo concreto los métodos usados para hacer la asignación que corresponde según la opción elegida, los crearemos de forma anónima, es decir, será una expresión lambda en lugar de un método de evento real, ahora lo veremos en el código.

Empecemos por las declaraciones de las variables y el método getElementRect que es el que se encarga de indicar qué opción del menú es la que se ha elegido (si es que se ha elegido alguna).

VB:

''' <summary>El idioma a usar</summary>
Private culLanguage As String = "es"

''' <summary>Contiene el texto para Español</summary>
Private culEs As String = "Español"
''' <summary>Contiene el texto para Inglés</summary>
Private culEn As String = "Inglés"


''' <summary>
''' Para saber el menú elegido
''' </summary>
''' <remarks>
''' Del ejemplo de la SDK: Context menu sample
''' </remarks>
Private Function getElementRect(element As FrameworkElement) As Rect
    Dim buttonTransform As GeneralTransform = element.TransformToVisual(Nothing)
    Dim point As Point = buttonTransform.TransformPoint(New Point)
    Return New Rect(point, New Size(element.ActualWidth, element.ActualHeight))
End Function

 

C#:

/// <summary>El idioma a usar</summary>
private string culLanguage = "es";

/// <summary>Contiene el texto para Español</summary>
private string culEs = "Español";
/// <summary>Contiene el texto para Inglés</summary>
private string culEn = "Inglés";


private static Rect getElementRect(FrameworkElement element)
{
    GeneralTransform buttonTransform = element.TransformToVisual(null);
    Point point = buttonTransform.TransformPoint(new Point());
    return new Rect(point, new Size(element.ActualWidth, element.ActualHeight));
}

Ahora le toca el turno al método del evento clic del botón de idioma.

Empezaremos creando una variable del tipo PopupMenu a la que le añadimos dos opciones (menús o comandos). La forma de añadirlo es mediante el método Add de la propiedad/colección Commands, Lo que espera ese método es un objeto del tipo UICommand. Así que, lo creamos directamente en la asignación, y en la sobrecarga que estamos utilizando los parámetros que el constructor de los comandos espera recibir son: el texto a mostrar y la dirección (puntero) de un método que cumpla con el delegado UICommandInvokedHandler.

Como ya te comenté antes, el método para ese segundo parámetro lo vamos a definir directamente, es decir, como un método anónimo o función lambda. Y en ese "método" lo que haremos es simplemente asignar un valor a una variable para saber qué idioma usar. Que el usuario elige el primer menú, asignamos "es", que elige el segundo, asignamos "en".

Veamos el código del método buttonLang_Click tanto para Visual Basic como para C#:

VB:

''' <summary>
''' Al pulsar en el botón, mostrar el menú contextual
''' En otros casos se puede usar el evento RightTapped
''' </summary>
Private Async Sub buttonLang_Click(sender As Object, e As RoutedEventArgs)
    Dim menu = New PopupMenu
    Dim sLang As String = "es"

    menu.Commands.Add(New UICommand(culEs, Sub(command) sLang = "es"))
    menu.Commands.Add(New UICommand(culEn, Sub(command) sLang = "en"))

    Dim chosenCommand = Await menu.ShowForSelectionAsync(
                                Me.getElementRect(TryCast(sender, FrameworkElement)))

    ' The command is null if no command was invoked.
    If chosenCommand IsNot Nothing Then

        culLanguage = sLang

        'guardarConfig()

        'cambiarIdioma()

        '' Eliminar las notificaciones anteriores y usar nuevas
        '' para que se utilice el nuevo idioma indicado
        'borrarTileNotifications()

        asignarTiles()

    End If
End Sub

 

C#:

/// <summary>
/// Al pulsar en el botón, mostrar el menú contextual
/// En otros casos se puede usar el evento RightTapped
/// </summary>
private async void buttonLang_Click(object sender, RoutedEventArgs e)
{
    var menu = new PopupMenu();
    string sLang = "es";

    menu.Commands.Add(new UICommand(culEs, (command) => sLang = "es"));
    menu.Commands.Add(new UICommand(culEn, (command) => sLang = "en"));

    var chosenCommand = await menu.ShowForSelectionAsync(
                                    getElementRect((FrameworkElement)sender));


    // The command is null if no command was invoked.
    if (chosenCommand != null)
    {
        culLanguage = sLang;

        //guardarConfig();

        //cambiarIdioma();

        //' Eliminar las notificaciones anteriores y usar nuevas
        //' para que se utilice el nuevo idioma indicado
        //borrarTileNotifications();

        asignarTiles();
    }
}

 

Y una vez que tenemos todo esto, si iniciamos la aplicación y pulsamos en la pantalla con el botón derecho (o secundario) del ratón (o mouse) veremos las dos opciones mostradas por encima del botón, tal como podemos apreciar en la figura 2:

menucontextual_02

Figura 2: La aplicación en funcionamiento dentro del emulador / simulador de un Windows 8 en un tablet.

 

En otra ocasión veremos el código de guardar (y leer) la configuración y un par de detalles a tener en cuenta ya que (como estarás comprobando) casi todos los métodos que utilizamos en las aplicaciones para la tienda de Windows son asíncronos y en ocasiones hay que "esperar" a que uno de esos métodos termine antes de seguir con el siguiente.

También veremos cómo cambiar los textos según el idioma elegido y por supuesto el método ese para borrar las notificaciones que hubiese pendientes de mostrar, ya que al cambiar el idioma el texto de los días y meses se muestran distintos en español que en inglés.

Ah, y el código de asignarTiles recuerda que el de VB ya estaba publicado en Actualizar cada minuto el icono (tile) de una aplicación de Windows Store hasta la hora indicada y ahora ya está también publicado el de C#.

 

Y ya que tenemos ese método para que "automatice" las notificaciones en el icono (tile) de la aplicación, hay que modificar el código que ya tenemos, con idea de que se utilice ese nuevo código.

Esos cambios te los mostraré en la próxima ocasión, cuando te muestre el código de borrarTileNotifications.

¡Hasta entonces!

 

Más abajo tienes los enlaces al resto de artículos de esta serie.

¡Espero que te sean de utilidad!

 

Nos vemos.

Guillermo

 

Enlaces a los otros artículos de este "paso a paso":

  1. Usar un temporizador en las aplicaciones de Windows store (Visual Basic)
  2. Usar un temporizador en las aplicaciones de Windows store (C#)
  3. Pon una AppBar en tu aplicación de Windows Store
  4. Acceder a los recursos de una aplicación de Windows Store desde código (vb, c#, xaml)
  5. Actualizar el icono (tile) de una aplicación de Windows Store (cada minuto)
  6. Saber cuando la aplicación está en modo Snapped y actuar en consecuencia

Esta entrada fue publicada en cosas técnicas, mis cosas y etiquetada , , , , , , , , . Guarda el enlace permanente.