Etiqueta: C#Sharp

Temas relacionados con C#

  • 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

    …

  • Actualizar cada minuto el icono (tile) de una aplicación de Windows Store hasta la hora indicada

    Pues eso, un titulo más largo que el del artículo que publiqué hace unos días:
    Actualizar el icono (tile) de una aplicación de Windows Store,
    en el que te contaré cómo indicarle a Windows que actualice lo que se muestra en el icono de la aplicación (tile), pero incluso cuando dicha aplicación ya está cerrada, además esa actualización se hará cada "x" tiempo y hasta cuando tu digas (la cantidad de minutos u horas que quieras que duren esas actualizaciones).

    El código te lo mostraré primero para Visual Basic y cuando lo tenga listo en C# lo agregaré a esta misma "página" (con fecha del domingo 23 de diciembre de 2012 ya está el código de C#, pero lo he puesto al final del todo y sin usar el fondo negro).

    Dicho esto, crea una nueva aplicación para Windows Store (la más básica es suficiente).

    En el código del evento OnNavigatedTo de MainPage añade esta llamada al método que hará todo el trabajo: asignarTiles.

     

    Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
        asignarTiles()
    End Sub
    
    

     

    Y ahora viene cómo hacer esto de modificar (si quieres, llámalo notificar) el contenido del icono de la aplicación (conocido como tile por los que ponen nombres a estas cosas nuevas que van saliendo). Pero para hacer esa modificación no tendremos que usar ningún temporizador (timer) simplemente usaremos una serie de asignaciones a un objeto del tipo TileUpdater creado a través del método CreateTileUpdaterForApplication de la clase TileUpdateManager a través del método AddToSchedule de forma que le digamos lo que se mostrará en el icono (ya sea el grande -ahora hablamos de ese icono- o el pequeño) y, lo más importante, cuándo se mostrará.

    Nota:

    Este código está adaptado del ejemplo Clock Tile de Dave Smits.

    Te dejo el código y espero que lo comprendas… si tienes dudas pregunta en los comentarios de este mismo post… eso si antes no te lo he explicado con más detalle.

    Recuerda que el cuadro del código puede tener scroll y no lo veas al completo…

     

    Lo que sí (o también, si ya te he explicado lo que te iba a explicar) te voy a decir que al crear un nuevo proyecto para Windows Store (al menos del más elemental) el icono ancho no estará y por tanto el icono (o tile) de la aplicación se mostrará en el formato cuadrado (pequeño). Esa imagen es la que se llama Logo.png en la carpeta Assets y su tamaño es de 150×150. Para tener el logo de tamaño ancho, necesitarás una imagen de 310×150 a la que tendrás que darle el nombre WideLogo.png. Si no haces esto, este ejemplo no compilará.

     

    ''' <summary>
    ''' Crear la lista de notificaciones al icono (tile)
    ''' Se crearán los necesarios para las próximas 4 horas
    ''' notificando cada minuto
    ''' </summary>
    ''' <remarks>
    ''' Basado en el código de Clock Tile de Dave Smits
    ''' </remarks>
    Private Sub asignarTiles()
        Dim tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication()
    
        Dim now As DateTime = DateTime.Now
        ' aquí está el truco... crear tiles para un buen rato...
        Dim planTill As DateTime = now.AddMinutes(30) ' .AddHours(4) ' .AddMinutes(15)
    
        Dim updateTime = New DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0).AddMinutes(1)
    
        Dim plannedUpdated = tileUpdater.GetScheduledTileNotifications()
        If plannedUpdated.Count > 0 Then
            ' Asignar a updatetime la última fecha de la colección (o la que sea mayor)
            updateTime = plannedUpdated.Select(Function(x) x.DeliveryTime.DateTime).Union({updateTime}).Max()
        End If
        Const sXml = "<tile><visual>" &
                            "<binding template=""TileSquareText02""><text id=""1"">{0}</text><text id=""2"">{2}</text></binding>" &
                            "<binding template=""TileWideText01""><text id=""1"">{0}</text><text id=""2"">{1}</text>" &
                                "<text id=""3""></text><text id=""4""></text><text id=""5""></text></binding>" &
                    "</visual></tile>"
    
        Dim tileXmlNow = String.Format(sXml, now.ToString("HH:mm"),
                                             now.ToString("dddd, dd MMMM yyyy"),
                                             now.ToString("dd/MMM/yyyy"))
        Dim documentNow As New XmlDocument()
        documentNow.LoadXml(tileXmlNow)
    
        tileUpdater.Update(New TileNotification(documentNow) With {.ExpirationTime = now.AddMinutes(1)})
    
        Dim startPlanning = updateTime
        While startPlanning < planTill
    
            Try
                Dim tileXml = String.Format(sXml, startPlanning.ToString("HH:mm"),
                                                  startPlanning.ToString("dddd, dd MMMM yyyy"),
                                                  startPlanning.ToString("dd/MMM/yyyy"))
                Dim document As New XmlDocument()
                document.LoadXml(tileXml)
    
                Dim deliveryTime = New DateTimeOffset(startPlanning)
                Dim scheduledNotification = New ScheduledTileNotification(document, deliveryTime)
                scheduledNotification.ExpirationTime = startPlanning.AddMinutes(1)
    
                tileUpdater.AddToSchedule(scheduledNotification)
    
            Catch e As Exception
                Debug.WriteLine("exception: " & e.Message)
    
            End Try
    
            startPlanning = startPlanning.AddMinutes(1)
        End While
    
    End Sub
    

     

    Bueno, y esto es todo… si cierras la aplicación (sólo te mostrará una pantalla negra) verás que el icono se sigue actualizando y cuando pase el tiempo indicado (en este ejemplo es de 30 minutos) se asignará el texto original.

    El tiempo total en el que se estarán mostrando las notificaciones es el indicado en la definición de la variable PlanTill:

    Dim planTill As DateTime = now.AddMinutes(30)

     

    Por cierto, creo que el número máximo de "actualizaciones / notificaciones" al tile de la aplicación es de 4096, así que… lo mismo habría que tener en cuenta que no se sobrepase esa cantidad… (tendré que probar si da error o no al pasar de esa cantidad).

     

    Espero que te sea de utilidad.

    Nos vemos.

    Guillermo

    P.S.

    El "estilo" del código es el que Visual Studio 2012 utiliza cuando está en modo "Dark"… a mi no me acaba de convencer…

     

    Nota del 23/Dic/12: el código de C#

    /// <summary>
    /// Crear la lista de notificaciones al icono (tile)
    /// Se crearán los necesarios para las próximas 4 horas
    /// notificando cada minuto
    /// </summary>
    /// <remarks>
    /// Basado en el código de Clock Tile de Dave Smits
    /// </remarks>
    private void asignarTiles()
    {
        var tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication();
    
        DateTime now = DateTime.Now;
        // aquí está el truco... crear tiles para un buen rato...
        DateTime planTill = now.AddMinutes(30); // .AddHours(4)
    
        var updateTime = new DateTime(now.Year, now.Month, now.Day, 
                                      now.Hour, now.Minute, 0).AddMinutes(1);
    
        var plannedUpdated = tileUpdater.GetScheduledTileNotifications();
        if (plannedUpdated.Count > 0)
        {
            // Asignar a updatetime la última fecha de la colección (o la que sea mayor)
            updateTime = plannedUpdated.Select(
                x => x.DeliveryTime.DateTime).Union(new[] { updateTime }).Max();
        }
    
        const string sXml = 
            @"<tile><visual>
                <binding template=""TileSquareText02"">
                    <text id=""1"">{0}</text><text id=""2"">{2}</text>
                </binding>
                <binding template=""TileWideText01"">
                    <text id=""1"">{0}</text><text id=""2"">{1}</text>
                    <text id=""3""></text><text id=""4""></text><text id=""5""></text>
                </binding>
            </visual></tile>";
    
        var tileXmlNow = String.Format(sXml, now.ToString("HH:mm"),
                                             now.ToString("dddd, dd MMMM yyyy"),
                                             now.ToString("dd/MMM/yyyy"));
        XmlDocument documentNow = new XmlDocument();
        documentNow.LoadXml(tileXmlNow);
    
        tileUpdater.Update(new TileNotification(documentNow) { ExpirationTime = now.AddMinutes(1) });
    
        // Este bucle while se puede cambiar por este for:
        // for (var startPlanning = updateTime; startPlanning < planTill; startPlanning = startPlanning.AddMinutes(1))
        var startPlanning = updateTime;
        while (startPlanning < planTill)
        {
            try
            {
                var tileXml = String.Format(sXml, startPlanning.ToString("HH:mm"),
                                                  startPlanning.ToString("dddd, dd MMMM yyyy"),
                                                  startPlanning.ToString("dd/MMM/yyyy"));
                XmlDocument document = new XmlDocument();
                document.LoadXml(tileXml);
    
                var deliveryTime = new DateTimeOffset(startPlanning);
                var scheduledNotification = new ScheduledTileNotification(document, deliveryTime);
                scheduledNotification.ExpirationTime = startPlanning.AddMinutes(1);
    
                tileUpdater.AddToSchedule(scheduledNotification);
            }
            catch (Exception e)
            {
                Debug.WriteLine("exception: " + e.Message);
            }
            startPlanning = startPlanning.AddMinutes(1);
        }
    }
    

     

    …

  • Saber cuando la aplicación está en modo Snapped y actuar en consecuencia

    Pues eso… que en las aplicaciones de Windows 8 (Windows Store) la forma de verla puede ser de tres formas distintas: que ocupe toda la pantalla (el modo predeterminado), que ocupe una parte más pequeña en uno de los laterales (modo snapped o acoplada) o que ocupe la parte grande (filled o vista de relleno) cuando otra aplicación esté en modo snapped.

    Para aclarar estos conceptos, te muestro en la figura 1 cómo se vería una aplicación a vista completa o en modo acoplado (esta imagen está sacada de: Directrices para vistas acopladas y rellenas (aplicaciones de la Tienda Windows).

     

    snappd_01
    Figura 1. Una aplicación que va de pantalla completa a vista acoplada

     

    Cuando la aplicación está en modo "relleno" el tamaño es aceptablemente grande como para que tengamos que preocuparnos demasiado, pero cuando está en modo acoplado (snapped) ahí si que hay que tener en cuenta que el contenido puede que no sea el adecuado.

    Por ejemplo, nuestra aplicación de reloj se vería así:

    snappd_02
    Figura 2. La aplicación de reloj acoplada a la izquierda

     

    Por tanto, para que el texto se adapte cuando esté en modo acoplado (snapped) vamos a escribir unas pocas líneas en las que simplemente cambiaremos el tamaño de la fuente de los dos textos mostrados, de esa forma, al acoplar la aplicación se verá más o menos como vemos en la figura 3.

     

    snappd_03
    Figura 3. Al acoplar la ventana de nuestra aplicación el texto se adapta

     

    Nota:
    El cambio de color (y aparentemente de tamaño) del botón Stop es porque la figura 2 está capturada del proyecto de C# y la captura de la figura 3 es del proyecto de Visual Basic en el que he cambiado el color predeterminado de los iconos y demás con idea de que no sean grises, si no de ese color azul.

     

    Veamos el código, el cual está en MainPage_SizeChanged y lo único que haremos es "empequeñecer" el tamaño de las fuentes cuando esté en modo Snapped y volver a poner el tamaño inicial al mostrarse en cualquiera de las otras dos formas.

    VB:

    ' En el evento SizeChanged de la página principal comprobamos
    ' si estamos en modo de vista Snapped y adaptamos el tamaño de las fuentes
    Private Sub MainPage_SizeChanged(sender As Object, e As SizeChangedEventArgs) _
    Handles Me.SizeChanged If ApplicationView.Value = ApplicationViewState.Snapped Then txtHora.FontSize = 36 txtFecha.FontSize = 18 Else txtHora.FontSize = 72 txtFecha.FontSize = 36 End If End Sub

     

    C#:

    // En el evento SizeChanged de la página principal comprobamos
    // si estamos en modo de vista Snapped y adaptamos el tamaño de las fuentes
    private void MainPage_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (ApplicationView.Value == ApplicationViewState.Snapped)
        {
            txtHora.FontSize = 36;
            txtFecha.FontSize = 18;
        }
        else
        {
            txtHora.FontSize = 72;
            txtFecha.FontSize = 36;
        }
    }
    

     

    En el caso de VB no tienes que hacer nada especial con ese código, simplemente lo pegas en MainPage.vb y ya está, pero en C# debes agregar el evento a ese método, eso lo tendrás que hacer (por ejemplo) en el código de diseño de MainPage.xaml justo antes del cierre de la definición de la página (elemento Page):

    mc:Ignorable="d" SizeChanged="MainPage_SizeChanged">
    
    

     

    Lo que hacemos en ese método de evento es bien simple, comprobamos si el valor de la propiedad Value de la clase ApplicationView (que está definida en el espacio de nombres Windows.UI.ViewManagement) tiene un valor Snapped, de ser así reducimos el tamaño de las fuentes y en caso contrario asignamos los valores "normales".

    En la página (de MSDN) de la enumeración ApplicationViewState puedes ver los cuatro valores soportados por esa enumeración y la descripción de cada uno de ellos.

     

    Y esto es todo por hoy… dentro de poco más… ¿el qué? ya veremos… porque en teoría la aplicación ya está como en un principio yo quería que estuviera, así que… lo mismo te pongo un resumen completo y el código fuente… ya veremos.

    En cualquier caso, espero que te sea de utilidad todo esto que te he contado, tanto en esta ocasión como en las anteriores (abajo tienes todos los enlaces).

     

    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

    …