Archivo de la etiqueta: metro

Preparando el examen 70-484

El pasado 30 de mayo aprobé el examen 70-484 de desarrollo de aplicaciones para Windows 8 con C#, lo que me acerca un paso más al MCPD en desarrollo de apps para la plataforma, y es a su vez una excusa y un reto para aprender más de la misma.

Al comentarlo por Twitter, algunos desarrolladores me preguntaron qué recursos había usado, y aquí va un pequeño resumen.

Sigue leyendo

Anuncios

Horizontal scroll with HTML5 for Windows Store apps

These days I have spent some of spare time developing an application for Windows 8 using the Karmacracy API. For this, I have tried to minimize the WinJS usage and default controls, while maintaining the design previously known as “Metro”. The result so far is this, although it may be subject to changes and improvements:

karmacracy-stage-6

In this article we will see how to get the horizontal scroll, keeping elements such as the title and the login box.

Sigue leyendo

Conseguir scroll horizontal con Javascript para aplicaciones Windows Store

En estos días he empleado algo de mi tiempo libre desarrollando una aplicación para Windows 8 usando la API de Karmacracy para la cual he intentado usar al mínimo WinJS y los controles por defecto, manteniendo, además, el diseño anteriormente conocido como “Metro”. El resultado hasta ahora es este, aunque está sujeto a cambios, y a mejoras:

karmacracy-stage-6

En este artículo veremos cómo conseguir el scroll horizontal, conservando elementos como el título y el cuadro de inicio de sesión.

Sigue leyendo

Angular.js para aplicaciones Windows Store

Existe una gran variedad de frameworks javascript, Angular, Ember, knockout, etc. Todos ellos nos proporcionan algo que aquellos que hemos hecho wpf estábamos esperando: Data binding, y la posibilidad de usar patrones como MVVM.

En este artículo doy un vistazo a Angular.js, un framework desarrollado por Google que está dando mucho de que hablar, y, para hacerlo más interesante, he lo empleo dentro del contexto de una aplicación Windows 8, donde las reglas del juego cambian ligeramente.

Instalación y configuración

Para este proyecto, el primer paso es crear una aplicación vacía de Windows 8 con Javascript, podemos usar Visual Studio Express para ello.

Para incluir Angular.js, una cosa que podemos pensar es enlazar directamente a la CDN de angular desde nuestro fichero default.html:

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js">
</script> 

Sin embargo nos encontramos con esto:

Usando la CDN de Angular JS

Es decir, no podemos usar una referencia no local para ficheros javascript con lo cual tendremos que descargarlo e incluirlo en nuestro proyecto manualmente. Podríamos además, estar tentados a instalarlo usando nuget, pero en mi opinión agrega demasiados archivos al proyecto.

Como anotación, recomiendo descargar la versión angular.js, no la angular.min.js, ya que tendremos que hacer algunos cambios más adelante.

Una vez tengamos el fichero agregado a nuestro proyecto, si intentamos compilar tendremos una segunda sorpresa:

Excepcion con angular

Hay muchas maneras de resolver este error, pero el que a mí me ha funcionado pasa por editar la función problemática, y sustituir la llamada a la función insertBefore por:

MSApp.execUnsafeLocalFunction(function ()
 {element.insertBefore(child, index);
});

Con este ligero cambio, ya podremos ejecutar nuestra aplicación.

Las vistas

Para mostrar información por pantalla, en vez de construir el HTML manualmente y editar el DOM desde código javascript, simplemente usamos ciertas convenciones para incrustar datos dentro de una plantilla HTML.

<label>Name:</label>
<input type="text" ng-model="yourName" 
placeholder="Enter a name here" />
<h1>Hello {{yourName}}!</h1>

En este caso, el input genera una variable de nombre yourName, que se actualiza en el campo h1, en la región habilitada para ello. Estas variables encerradas entre llaves se pueden usar también dentro de los elementos html, por ejemplo para fijar la propiedad “src” de una imagen:.

<img src="{{item}}" />

No tenemos que preocuparnos por la actualización, ya que al cambiar el contenido del dato, sea cual sea, el valor será actualizado automáticamente. Esto representa una diferencia bastante interesante respecto a otros frameworks como Knockout, donde para que se actualizara el objeto teníamos que definirlo con un tipo muy específico.

Controladores

El controlador se define como una clase javascript, con propiedades y funciones, las cuales luego suelen ser llamadas desde el código fuente, por ejemplo:

function TodoCtrl($scope) {
$scope.todos = [];

$scope.addTodo = function () {
$scope.todos.push({ text: $scope.todoText, done: false });
        $scope.todoText = '';
};

};

En este ejemplo se define un controlador, un campo llamado todos, y un método para almacenar en la lista el valor definido en la variable todoText. El $context es similar al this del standard, aunque con algunas variantes. La vista de este código se parece a algo así:

<h2>Todo</h2> {{todos.length}}
<form ng-submit="addTodo()">
    <input type="text" ng-model="todoText" placeholder="add new todo here" size="30" />
    <input class="btn-primary" type="submit" value="add" />
</form>

A diferencia de lo visto anteriormente, en este código definimos un controlador, accedemos al campo length del objeto todos definido anteriormente, y finalmente llamamos al método como resultado del envío de formularios.

Bucles (y bucles dentro de bucles)

Otra de las cosas interesantes que tiene, es el uso de los bucles para recorrer información:

<ul>
    <li ng-repeat="todo in todos">
        <p>{{todo.name}}</p>
        <span ng-repeat="item in todo.items">
            <img src="{{item}}" /></li>
    </li>
</ul>

En este caso representamos la estructura de todos, y asumiendo que todo es una estructura compuesta, Estos bucles además se pueden anidar, consiguiendo una mayor libertad a la hora de representar datos complejos.

Llamadas HTTP

Para poder hacer llamadas a un servidor externo mediante http solamente necesitamos la url y el método por el cual realizaremos la petición, para efectuar la llamada de la siguiente manera:

$http({ method: 'GET', url: 'http://url' }).
 success(function (data, status, headers, config) {

}).
 error(function (data, status, headers, config) {

});

Este código lo incluiremos en nuestro controlador sin llamadas adicionales, de tal manera que sea ejecutado al cargar el controlador. Si lo hacemos de esta manera nos encontraremos con un bonito error como el que se muestra a continuación:

Http error

Para evitar ese error, hemos de modificar la definición de nuestro controlador:

function TodoCtrl($scope)

De tal manera que ahora además de $scope, recibe $http:

function TodoCtrl($scope, $http)

Resumen

Esto es solamente una primera toma de contacto, y he de decir que la primera impresión ha sido muy buena. La documentación y la cantidad de ejemplos disponibles en internet ayudan también a que la curva de aprendizaje sea simple.

Enlaces adicionales

Viernes 22: Desarrollo para Windows Phone y Windows 8 en la Universidad de Salamanca

El próximo viernes 22 a partir de las 5 PM estaré en la Facultad de Ciencias de la Universidad de Salamanca con los chicos de @DotNetUSAL, hablando de desarrollo para aplicaciones Windows 8 y Windows Phone.

BZXb95zCcAI1UHD

Durante un buen tramo de la tarde estaremos viendo qué ventajas nos da la plataforma Windows Phone y Windows 8, y cómo aprovechar esas ventajas para que nuestras aplicaciones destaquen por encima del resto.

Las herramientas de desarrollo están disponibles en los siguientes enlaces:

Para hacer la charla más dinámica, usaremos VS Anywhere para que todos los asistentes que lo deseen puedan contribuir a la misma, y seguir las demos desde su ordenador. Si quieres aprender de una manera diferente, crea tu cuenta en http://vsanywhere.com y descarga el plugin:

VS Anywhere requiere Visual Studio Professional o superior, que puedes conseguir gratuitamente a través del programa Dreamspark. Si no lo tienes pregunta a los chicos de @DotNetUSAL cómo conseguirlo.

Por otra parte, tienes versiones de prueba de 90 días de cualquiera de las versiones de Visual Studio 2013 en este enlace: http://www.visualstudio.com/downloads/download-visual-studio-vs

Nos vemos en Salamanca!

Datos locales en aplicaciones para Windows Store: Serialización de objetos

En un artículo anterior comentaba una de las posibilidades de almacenamiento de datos en aplicaciones Metro, los diccionarios clave-valor. Esto permitía, recordemos almacenar datos simples de una manera fácil y sencilla, aunque en ocasiones, querremos almacenar datos un poco más complejos. En este artículo se verá cómo almacenar objetos complejos sin tener que recurrir a una base de datos.

Pese a que la API de WinRT incluye todos los componentes necesarios para guardar los datos, hay bibliotecas de clases que nos facilitan mucho la vida. Concretamente esta, Generic Object Storage Helper for WinRT nos permite almacenar objetos y obtenerlos con pocas líneas de código.

Clase a guardar

Para este ejemplo, la clase que almacenaremos será una clase Person. Es requisito que las clases que se almacenen sean serializables, aunque no es necesario que incluyan el atributo. Existen limitaciones, claro, ya que por ejemplo, una ObservableCollection no se puede serializar, una imagen o un objeto de tipo URI tampoco. Además, tiene una ventaja muy interesante, y es que se pueden guardar listas con la misma facilidad, como se verá en el ejemplo.

public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string PictureURL { get; set; }
        public Person Mother { get; set; }
        public Person Father { get; set; }
    }

Una vez obtenido el componente, se puede agregar el componente WinRtUtility.dll a la solución y ya se puede emplear.

Eligiendo el tipo de guardado y almacenando los datos

Podemos guardar los datos en tres espacios diferentes:

  • Local: Los datos se almacenan en el espacio de la aplicación en el dispositivo. Se borran del dispositivo cuando se elimina la aplicación.
  • Roaming: Los datos se almacenan en el espacio del usuario, de esta manera, si se accedes a la app desde otro ordenador donde esté iniciada la sesión con su cuenta Microsoft, se podrán obtener estos mismos datos.
  • Temp: Almacenamiento temporal y volátil, datos que podamos desechar.

Para almacenar los datos, solamente son necesarias las dos líneas siguientes:

var objectStorageHelper = new ObjectStorageHelper&lt;List&gt;(StorageType.Local);
objectStorageHelper.SaveAsync(personObject);

En la primera línea de código se establece el tipo de objeto a guardar así como el espacio en que se hará el guardado. En la segunda es en la que se realiza en guardado del objeto, de manera asíncrona siguiendo con los patrones de WinRT.

Estas líneas se pueden situar en el método OnSuspending, convenientemente situado para que su ejecución sea asíncrona, y situado en el fichero App.xaml.cs:

        private async void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: Save application state and stop any background activity
            var objectStorageHelper = new ObjectStorageHelper&lt;List&gt;(StorageType.Local);
            await objectStorageHelper.SaveAsync(Persons);
            deferral.Complete();
        }

Carga de los datos

La carga de los datos es tan sencilla como el guardado, ya que se emplean dos líneas muy similares a las vistas anteriormente:

var objectStorageHelper = new ObjectStorageHelper&lt;List&gt;(StorageType.Local);
Persons = await objectStorageHelper.LoadAsync();

Estas líneas se pueden situar en el método OnLoad, una vez más, modificado para que se ejecute de manera asíncrona:

        protected async override void OnLaunched(LaunchActivatedEventArgs args)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                if (args.PreviousExecutionState != ApplicationExecutionState.Suspended)
                {
                    var objectStorageHelper = new ObjectStorageHelper&lt;List&gt;(StorageType.Local);
                    Persons = await objectStorageHelper.LoadAsync();
                }
                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            [...]
            // Ensure the current window is active
            Window.Current.Activate();
        }

Conclusiones

En este artículo se ha visto que existe otra opción para el almacenamiento de estructuras de datos más complejas utilizando poco más que de dos líneas de código situadas en los eventos de carga y guardado de la aplicación.

Más información:

Estado de conexión para aplicaciones Metro

Uno de los requisitos que necesita cumplir nuestra aplicación Metro para su correcta validación es que sea capaz de comportarse correctamente sin conexión a internet. En este artículo veremos 2 maneras de obtener esta información, o bien de manera activa, solicitando el estado del perfil de conexión, o bien de manera pasiva, suscribiendonos a un evento.

Solicitando el perfil de conexión

El siguiente código fuente hace uso de la clase NetworkInformation para consultar el tipo de perfil que tiene la aplicación. En caso de ser nulo, significa que el sistema no tiene ninguna manera de conectarse a Internet.

var profile = NetworkInformation.GetInternetConnectionProfile();
if (profile == null)
{
  //No tenemos ninguna conexión disponible.
}
else
{
  //Al parecer, tenemos internet, pero tenemos que ver que tipo.
}

Sin embargo, el hecho de tener un perfil de conexión no nulo no garantiza la correcta conexión a la red, ya que podemos tener un perfil válido sin conexión. Esto es lo que comprueba la segunda parte del código mostrado.

  var level = profile.GetNetworkConnectivityLevel();
  if(level == NetworkConnectivity.LocalAccess || level == NetworkConnectivityLevel.None)
  {
     //Tenemos conexión, pero no tenemos acceso a internet.
  }

Deberemos ser capaces de informar correctamente a nuestros usuarios del estado de la conexión de manera no intrusiva, este último parámetro es muy importante.

Recibiendo de manera activa los cambios que ocurran con la conexión

La segunda manera de saber el estado de la red, es que nuestra aplicación informe al usuario si existen cambios en la red (cambio de conectado a desconectado y viceversa). Afortunadamente la clase NetworkInformation proporciona un evento al que podemos suscribirnos y obtener esta información:

En la página principal. nos suscribimos al evento:

public MainPage()
{
  this.InitializeComponent();
  NetworkInformation.NetworkStatusChanged += NetworkInformation_NetworkStatusChanged;
}

Posteriormente, hacemos una llamada al dispatcher para poder actualizar la interfaz de usuario (ya que, de otra manera obtendremos una excepción):

async void NetworkInformation_NetworkStatusChanged(object sender)

  await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,UpdateUI);
}

Finalmente, actualizamos la interfaz de usuario con el mensaje más apropiado:

private void UpdateUI()
{
  //Informar al usuario del cambio de condiciones de la red.
}

Conclusiones

Estos dos ejemplos los podemos combinar para mejorar la experiencia del usuario, y con ella la calificación de nuestra aplicación,

Más información: