Etiqueta: Windows 8

  • Las plantillas de Windows Store o la dejadez para con Visual Basic

     

    Pues eso… que "trasteando" con las plantillas (tipos de aplicaciones) para Windows Store usando Visual Basic como lenguaje de programación, me he topado con un par de "chorradas" que aunque no son importantes creo que son muestra de, siendo benévolo (por aquello de las fechas en que estamos), un poco de dejadez por parte de "a quién corresponda".

    Nota del 29/Dic/12:
    He agregado un extra…

    Me estoy refiriendo a las plantillas de proyectos para Windows Store de más de una página es decir: GridApp y SplitApp (ver la figura 1).

     

    proyectos_appstore
    Figura 1. Crear un nuevo proyecto para Windows Store con Visual Basic

     

    Si tienes Option Strict On, es decir: ser estricto con las declaraciones y sobre todo con las asignaciones, lo primero que te encuentras es con esta asignación en App.xaml.vb:

    Dim rootFrame As Frame = Window.Current.Content
    
    

    Y la comprobación estricta te indica que esa conversión implícita no es correcta, por suerte, Visual Basic nos ofrece una solución a ese error, tal como vemos en la figura 2, en la que propone que hagamos la conversión con CType.

     

    error de conversion implicita

    Figura 2. Error de conversión implícita y la solución

    Como vemos, la conversión de tipos propuesta es usando CType aunque yo prefiero usar TryCast que es más liviano sobre todo si sabemos que esa conversión es correcta y no producirá un error en tiempo de ejecución.

     

    TryCast devuelve un valor nulo si no puede hacer la conversión, mientras que CType producirá una excepción.

     

    Otra de esas "chorradillas" que te comento que me he encontrado es en el método ItemsCollectionChanged de la clase SampleDataGroup que está en la carpeta DataNodel de estos dos proyectos.

    En dos de los "Case" que realiza al hacer una doble comprobación, es decir, comprueba si esto y aquello está ocurriendo, utilizar And en lugar de AndAlso.

    ¡¡¡ En este código vemos las dos líneas que contienen los operadores And fatídicos !!!

     

    If e.NewStartingIndex < 12 And e.OldStartingIndex < 12 Then
    
    
    While TopItems.Count < Items.Count And TopItems.Count < 12

     

    Puede que creas que no es para tanto, pero si de verdad conoces lo que hace cada uno de esos dos operadores… La cuestión es que yo no utilizo And para una comparación desde que salió la primera versión de Visual Basic para .NET, de hecho antes casi tampoco la usaba y prefería hacer una doble comprobación: usar dos Ifs en lugar de usar And.

    Además la documentación de Visual Studio sobre el operador And te indica la diferencia entre And y AndAlso:

    En una comparación booleana, el operador And evalúa siempre las dos expresiones, lo que podría incluir llamadas a procedimientos. AndAlso realiza un cortocircuito, lo que significa que si expression1 es False, no se evalúa expression2.

     

    Lo curioso de esos And es que si el código está convertido de C# es extraño que no conviertan adecuadamente el operador usado en C#: &&, pero bueno… como And también puede ser un solo ampersand: & pues… es fácil que el conversor de código se equivoque.

     

    Ya te dije que eran cosas triviales, pero en ocasiones ver que no se cuidan esos pequeños detalles te pueden hacer pensar si habrá algo más que también pueda fallar… ¡esperemos que no! 😉

     

    Nos vemos.

    Guillermo

     

    Más de lo mismo (addendum del 29 de diciembre de 2012):

    Efectivamente, tiene toda la pinta de ser una traducción de C# a Visual Basic, pero "presuntamente" sin mucho cuidado en el resultado final (o casi), ya que en la clase SampleDataSource, concretamente en el constructor se asignan ciertos valores de prueba y una cadena con el contenido, que no es más que la misma cadena repetida varias veces, pero en C# usan \n\n para crear cambios de líneas y en VB lo han dejado con esos mismos "retornos de línea" que no hacen más que mostrar esos caracteres en la cadena en lugar de hacer los cambios de línea.

    La posible solución a esta "chorradilla" de fallo sería algo así:

    Dim ITEM_CONTENT As String = String.Format("Item Content: {0}{1}{0}{1}{0}{1}{0}{1}{0}{1}{0}{1}{0}",
                "Curabitur class aliquam vestibulum nam curae maecen ..."
                vbCrLf)
    
    

     

    Pues eso… en fin… es que me hierve la sangre… si no quieren que usemos el Visual Basic, ¡que lo quiten! pero si lo dejan que esté donde tiene que estar: en lugar preferente.

    …

  • 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

    …

  • Saber la versión de una aplicación de Windows Store

     

    Pues eso… quería mostrar la versión de mi aplicación en la página de "acerca de" y al buscar en Google (aparte de ver que tiene un doodle para el 13º Baktún de los mayas) me he encontrado con un artículo/truco de Caio Proiete en el que lo muestra para C# y JavaScript, y como yo suelo usar Visual Basic como lenguaje de programación, pues… lo he convertido, que no es que sea muy complicado hacerlo (lo de convertir de C# a VB) así que… aquí lo tienes tal y como yo lo estoy usando.

     

    Dim version = Windows.ApplicationModel.Package.Current.Id.Version
    Dim sVersion = String.Format("{0}.{1}.{2}.{3}",
                                 version.Major, version.Minor,
                                 version.Build, version.Revision)
    

     

    Espero que te sea de utilidad.

     

    Nos vemos.
    Guillermo

    …