Ayer me llegó por sorpresa un correo de Microsoft en el que se me indicaba que he sido nominado como Microsoft Active Professional 2013, abreviado como MAP (Me llaman Map, Bing Map… jejeje). He tenido que buscarlo porque era la primera vez que oía hablar de este reconocimiento y… ¡vaya sorpresa! Me ha alagado saber que me lo otorgan como distinción entre el 5% de los mejores profesionales. Como siempre digo, tengo mucho que aprender y hay muchísimas personas que deberían recibir reconocimientos antes que yoporque son auténticos cracks, pero lo son en la sombra porque por diferentes circunstancias no disponen de visibilidad en la comunidad. A todos ellos, les diré que se animen que hay un mundo de oportunidades y momentos de gran valor.
A Microsoft, gracias por este reconocimiento que me anima a seguir compartiendo los conocimientos y la experiencia que voy adquiriendo día a día con mi trabajo o con mis estudios e investigaciones.
A mis compañeros, en especial a mi maestro JediAlberto Díaz gracias por mostrarme el camino (y por los latigazos con el latigus 3000 =oP).
A todos, deciros que intentaré estar a la altura del reconocimiento en la medida de los posible.
Cuando programamos una SharePoint App “autohosted” tenemos que tener en cuenta que al instalarla se pierde el entorno de SharePoint porque lo que se hace es una especie de redirección desde SharePoint al sitio donde se ubica la App que publicamos. Por lo tanto, nuestra aplicación se verá como una web independiente de SharePoint y puede que no nos interese que sea así, sino que la aplicación esté dentro del entorno y del contexto de SharePoint 2013 manteniendo cabecera y menú.
Solución
Una vez hayamos creado el proyecto con la SharePoint App, tendremos una página default.aspx que por defecto está establecida como la página inicial del proyecto y que no contiene nada, salvo el nombre del sitio de SharePoint al que está asociada y que se inyecta desde el Code Behind.
Para lograr mi objetivo tenía que buscar la forma de insertar los scripts de SharePoint 2013 dentro de la página de mi aplicación y… buscando un poco en Bing (jejeje….) di con esta página de la MSDN que, aunque está un poco desactualizada, explican bien el concepto de lo que quiero y también incluyen el código que necesito para lograrlo. Pero como no es exactamente igual que como pone ahí porque hay algunas cosas que no son necesarias, quería explicarlo a mi manera.
En primer lugar, tenemos diferentes opciones, casi iguales, para incluir el Chrome de SharePoint 2013 dentro de nuestra App. Aquí exponen dos de ellos y yo me decanté por el más sencillo que es el segundo, denominado declarativo en el artículo.
1: <headrunat="server">
2: <title>Santiago Porras Rodríguez - My SharePoint App with Chrome control</title>
Se carga la librería Javascript de Ajax desde el CDN de Microsoft.
Se carga jQuery. Yo lo he cargado localmente al proyecto pero podemos sustituirlo por el que se encuentra en el CDN de Microsoft.
En el bloque de Javascript que viene a continuación se encuentran dos partes bien diferenciadas:
Cuando se haya cargado la página, se establece la dirección del Host de SharePoint 2013 (hostweburl) y se intenta cargar la librería Javascript SP.UI.Controls.js que es la que nos interesa para nuestro caso.
La función getQueryStringParameter que es llamada desde el punto anterior, nos sirve para obtener la dirección del servidor de SharePoint.
En el código HTML tenemos que realizar varios cambios:
Crear un divisor al que asignaremos un id, por ejemplo “chrome_ctrl-container” y en el que tenemos que incrustar las propiedades que están establecidas en el ejemplo.
Crear un divisor con id “MainContent” en el que incluimos el contenido de nuestra App (más que nada para tenerlo organizado, cosa que os puede salvar de muchos problemas)
Además, como opcional, podemos añadir Título y subtítulo en la página tal y como se muestra en el ejemplo.
Si ahora ejecutamos nuevamente la aplicación, el resultado es bien diferente, más agradable y, como estamos trabajando en SharePoint, mucho más lógico mantener el entorno (Chrome). Me he permitido el lujo de añadir un icono a la aplicación para darle algo de vida.
No obstante, hay otra forma muy similar de incluir el Chrome de SharePoint en nuestra App y que consiste en modificar levemente esta solución poniendo las propiedades del container dentro del bloque javascript. Esta opción que es la que finalmente he implementado en mi proyecto, nos permite separar más la lógica seguida para incluir el Chrome de SharePoint.
1: <headrunat="server">
2: <title>Santiago Porras Rodríguez - My SharePoint App with Chrome control</title>
El resultado final es el mismo que en la opción anterior como podréis comprobar
Finalmente, quería recordaros que para quitar la palabra “Dev” que me aparece a mi y que se corresponde con el nombre del sitio de SharePoint al que está vinculado la aplicación, tendréis que ir al archivo de Code Behind de la página, es decir a default.aspx.cs donde deberéis eliminar la línea siguiente:
1: Response.Write(clientContext.Web.Title);
También podéis eliminar el resto si no vais a usar el contexto de SharePoint.
En mi anterior artículo, hice una introducción de cómo construir una aplicación de LightSwitch para SharePoint en la que el escenario se centraba en poder enviar notificaciones push a usuarios de Windows Phone cada vez que se insertara un elemento en una lista de SharePoint. En este caso compartiré el código para realizar estos envíos.
Escenario
Teniendo una aplicación deLightSwitch en SharePoint que graba alertas en una lista, pretendemos que tras insertar el registro (o actualizarlo) se envíe una notificación push a los dispositivos Windows Phone registrados en una lista.
Solución
Si seguisteis el anterior artículo, veríais que en el código de la aplicación, concretamente en el Helper “AlertsHelper”, programé un método AddAlert que se encargaba de registrar la alerta en SharePoint y, además, tenía una llamada a la función SendPushNotification. Este es el momento de desvelar el código de dicho método por si algún día necesitáis hacer lo mismo.
En primer lugar, tenemos el método SendPushNotification que recibe como parámetros la alerta que queremos enviar a los dispositivos con Windows Phone y el contexto del sitio de SharePoint que nos servirá para obtener los dispositivos a los que tenemos que hacer el envío de la alerta y que están almacenados en una lista de SharePoint.
Como podéis observar, obtengo la lista de suscriptores por medio del contexto de sharepoint que le he pasado al método y, posteriormente ejecuto una consulta con CAML Query (sin filtro) para obtener todos los registros de la lista.
Una vez obtengo todos los registros, he de recorrer la colección de suscriptores creando un Toast Notification y, además, he añadido también un Tile Notification para que se vea si la aplicación está anclada al inicio. Ambos tipos de notificación son creados por medio del XML que los genera.
Haciendo uso de la URI correspondiente al canal del dispositivo y que obtengo del registro del suscriptor, hago una llamada al método SendMessage que es el encargado de abrir la petición y efectuar el envío. Esta llamada se realiza para cada uno de los tipos de notificación que he creado.
El método SendMessage abre la petición HTTP con la URI del canal del dispositivo, codifica el XML de la alerta en un array de Bytes, establece la cabecera HTTP en la que se especifica el tipo de notificación y su nivel de prioridad y realiza el envío de la alerta.
Por último, abro una conexión con la respuesta HTTP y, aunque no la estoy usando, podría comprobar el resultado del envío de la notificación. Lo he puesto para que comprobéis que se puede saber si la notificación ha sido enviada correctamente.
Estos días he tenido que trabajar con LightSwitchpara crear una aplicación que se conectara a SharePoint que pudiera interactuar con una “Lista Personalizada” (Custom List).
Escenario
Antes de comenzar, es necesario que establezca el contexto en el que LightSwitch se convirtió en la opción buena o menos mala (según se mire). La idea era bien simple, tener una lista de SharePoint de tipo “Custom List” en la que insertar alertas y que éstas sean notificadas por medio de Push Notifications a los usuarios con dispositivos Windows Phone. A priori esto podría resultar muy sencillo si disponemos de SharePoint Server 2013 server que ya dispone de un servicio de notificaciones, incluso en SharePoint 2010 server tampoco presenta un reto conseguir este objetivo pero, ¿qué ocurre con SharePoint Online? Independientemente de la versión, 2010 o 2013 preview, en el entorno online de SharePoint no disponemos de esta posibilidad de una forma trivial (al menos de momento) y tenemos que recurrir al desarrollo que, se nos complica porque nuestro objetivo incluye que la versión de SharePoint debe ser la 2013 online. Debido a estos “problemas”, hemos explorado diferentes medios por los cuáles alcanzar nuestro objetivo.
Primera opción
La primera de las opciones que evaluamos y, quizás la más lógica a priori, es el uso de un “Receptor remoto de eventos” (Remote Event Receiver) que es un nuevo elemento que trae SharePoint 2013 consigo y que consiste en un “servicio” que responde a los eventos que especifiquemos de unalista dentro de la app. Todo parecía ir genial, salvando ciertas complicaciones que se presentaron pero, finalmente descartamos esta opción porque nos fue imposible obtener el contexto (Context) del sitio de SharePoint desde el “Remote Event Receiver” y, era imprescindible que pudiéramos acceder a otra lista que contiene los usuarios/dispositivos a los que hay que enviar la “Push notification”.
Segunda opción
La segunda opción fue optar por LightSwitch, arriesgándonos al adentrarnos en terreno no habitual con la siguiente idea, crear una aplicación que recogiera las alertas, las propagara a la lista SharePoint y, además, leyera la lista de usuarios/dispositivos y les enviara la correspondiente Push Notification. Finalmente esta opción nos sirvió pero con algunos matices que explicaré más adelante.
Solución
El primer paso es crear nuestro proyecto de aplicación HTML de LightSwitch que usaremos para usar de pasarela entre SharePoint, sus listas y los dispositivos con Windows Phone de los usuarios.
Una vez se ha abierto el proyecto en blanco, deberíamos enlazar con la tabla de SharePoint online, peeeeero, es imposible realizar esta operación ya que SharePoint Online tiene problemas de autenticación con LightSwitch para esta acción, así que, procedemos a crear una tabla local a la aplicación de LightSwitch que llamaremos “Alerts” seleccionando la opción “Crear nueva tabla”
La tabla que he creado para las alertas contiendo los siguientes campos
Title: String
Body: String
DueDate: DateTime
AlertType: String (enumerado al que accedemos desde la opción “Choice List”)
Ahora vamos a proceder a crear las páginas que necesitamos para nuestra aplicación, un listado de alertas que llamaremos BrowseAlerts y un formulario de edición llamado AddEditForm. Para ello hacemos click con el botón derecho del ratón sobre el nodo “Cliente” de la solución y seleccionamos “Añadir pantalla” (Add Screen).
Una vez se abra el selector de pantalla, seleccionamos el tipo “Browse Data Screen” para el listado de alertas y en Screen Data seleccionamos “AlertasSet” o el conjunto que corresponda con nuestra tabla.
Procedemos a realizar la misma operación para crear la pantalla de edición pero, esta vez seleccionamos “Add/Edit Details Screen” en el tipo de pantalla y “Alertas” en “Screen Data”.
Ahora tenemos que enlazar las pantallas para que desde el listado tengamos la opción de abrir el formulario y crear una nueva alerta. Para ello, abrimos la pantalla “BrowseAlerts” que representa al listado y seguir estas indicaciones:
En el árbol que veremos seleccionar el nodo “List”, lo que hará aparecer la opción “Añadir”.
Seleccionar “Añadir” y ponerle un nombre.
De la lista de opciones seleccionar “Añadir botón”.
De la ventana que se abre, seleccionar “Elegir un método existente” y en Navigate To seleccionar “Alert Form”
Ahora que ya tenemos las pantallas enlazadas, tenemos que conectar nuestra aplicación con SharePoint. Para ello nos vamos a las propiedades del nodo del proyecto y en la sección SharePoint deberemos habilitar la conexión mediante el botón “Habilitar SharePoint”, lo que añadirá las referencias necesarias en nuestra aplicación para poder trabajar y, posteriormente deberemos poner la ruta de nuestro servidor.
Por último, nos queda escribir el código necesario para que al crear una nueva alerta en la aplicación de LightSwitch, ésta se propague a la lista que le indiquemos de SharePoint. Para conseguirlo, debemos ir primero a la vista de código de la aplicación.
Una vez tengamos la vista de código, en el nodo “Server” he creado una clase llamada “AlertHelper” que será la encargada de realizar la propagacióndel registro de la alerta.
19:// Comprobamos el contexto del servidor de SharePoint
20:if (siteContext == null)
21:thrownew InvalidOperationException("Could not retrieve the Sharepoint context");
22:
23:// Obtener la lista
24: List alertsList = siteContext.Web.Lists.GetByTitle("Alerts");
25:
26:// Recordar que siempre hay que hacer un Load y un ExecuteQuery
27: siteContext.Load(alertsList);
28: siteContext.ExecuteQuery();
29:
30:try
31: {
32:// Añadir la alerta a la lista
33: var alertItem = alertsList.AddItem(new ListItemCreationInformation());
34: alertItem["Title"] = alert.Title;
35: alertItem["Body"] = alert.Body;
36: alertItem["AlertType"] = alert.Type;
37: alertItem["Expires"] = alert.DueDate;
38: alertItem.Update();
39: siteContext.ExecuteQuery();
40: SendPushNotification(alert, siteContext);
41:returntrue;
42: }
43:catch (Exception ex)
44: {
45:returnfalse;
46: }
47: }
48: }
49: }
Ya sólo nos queda hacer que alguien llame al método de este “Helper”, y el encargado de hacerla será la clase “ApplicationDataService.cs” que se encuentra en la carpeta UserCode. Lo abrimos y le incluimos el método Alerts_Inserted que realizará la instancia del contexto del servidor de SharePoint y hará la llamada a la función del Helper que se encarga de propagar la alerta.
1:publicpartialclass ApplicationDataService
2: {
3:partialvoid Alerts_Inserted(Alert entity)
4: {
5: var appWebContext = this.Application.SharePoint.GetHostWebClientContext();
6: var a = Helpers.AlertsHelper.AddAlert(entity, appWebContext);
7: }
8:
9: }
Ahora ya lo tenemos todo listo y sólo nos queda ejecutar la aplicación y probar que funciona. Así es que le damos a F5, abriéndose así el navegador que nos pedirá autenticarnos en SharePoint y después nos mostrará una pantalla tal que así para “Confiar” en la aplicación que estamos desplegando. Seleccionamos “Trust It” para continuar.
El siguiente paso nos lleva a la aplicación de alertas, mostrando la pantalla de listado con el botón para añadir alertas tal y como hemos diseñado.
Añadimos las alertas que queramos, en este caso he añadido 4 alertas para poder tener una visión de la aplicación con datos.
Comprobamos en el listado que aparecen las alertas que vamos creando en la aplicación.
Hasta aquí todo correcto pero… ¿qué ocurre con la lista de SharePoint? ¿Se han propagado los datos? Navegamos hasta ella y comprobamos que todo ha salido correctamente.
Espero que os sirva de ayuda. En el siguiente artículo completaré el proceso con el envío de las alertas a los dispositivos Windows Phone.
Supongamos que tenemos una lista, llamémosla “fuente”, de SharePoint 2010 y queremos que al insertar o actualizar un elementos, se registre un log o un histórico en otra lista, llamémosla “destino”, es decir, insertar un registro en la otra lista con los datos que necesitemos. Para realizar esta operación deberíamos programar un EventReceiver y asignar nuestro código a los eventos deseado, ItemAdding, ItemAdded, ItemUpdating o ItemUpdated según sea el caso de nuestro escenario.
Solución
Tal y como ya avancé, tenemos que programar un EventReceiver asociado a la lista “fuente” y el evento deseado (Para el ejemplo he escogido ItemAdded), que se produce al insertar un nuevo registro. Lo que vamos a hacer es hacer una copia del registro insertado en la lista origen e insertarlo dentro de la lista destino.
25:// Se actualiza el registro en la lista para que los cambios tengan efecto
26: checkInItem.Update();
27: }
28: }
Posible problema
Hasta aquí todo debería ir bien pero, ¿qué ocurre si no tenemos permisos en la lista destino? Por lo general un usuario estándar no debería tener permisos en el “histórico” de un proceso y lo que ocurre es que este código se ejecuta en nombre del usuario que realiza la operación, es decir, el usuario logueado en el sistema y, más aún, el parámetro SPItemEventProperties properties que recibe el evento está compuesto por los elementos para los que tiene permisos el usuario actual, con lo que la lista destino no estaría presente, con lo que no sólo no se podría insertar el elemento, sino que ni siquiera se podría obtener la lista destino.
Solución
La solución pasa por ejecutar el código mediante RunWithElevatedPrivileges y dentro del código instanciar tanto la colección de sitios como el sitio en cuestión de forma tradicional
34:// Se actualiza el registro en la lista para que los cambios tengan efecto
35: checkInItem.Update();
36: }
37: }
38: }
39: });
40: }
Como podéis ver, se instancian de una forma tradicional tanto la colección de sitios como el sitio donde se encuentran las listas. De esta forma, obtendremos esos elementos y sus propiedades dentro del contexto de privilegios elevados gracias a que se encuentran dentro del bloque RunWithElevatedPrivileges y por lo tanto, sí tendremos acceso a la lista destino. Finalmente, el resto del código es exactamente igual al inicial.
Necesitamos ejecutar cierto código Javascript pero queremos que se haga al final de la carga de la página, por ejemplo si vamos a rellenar un input que no sabemos en qué momento estará disponible.
Solución jQuery:
Por todos es sabido a estas alturas que el problema se resolvería fácilmente haciendo uso de jQuery controlando el momento en el que la página esté “lista (ready)”, es decir:
1: $(document).ready(function() {
2:// Código a ejecutar
3:// ...
4: });
Pero estamos hablando de SharePoint 2010 que usa bastante Javascript para realizar acciones de carga o de control de los campos atendiendo a su tipo. Por lo tanto, ¿podemos asegurar que la página esté “lista (ready)” y que todo esté terminado de cargar cuando se ejecute $(document).ready(…)? Pues… aunque cueste creerlo, la respuesta es que no. SharePoint sigue haciendo algo de carga en algunos casos y, aunque como norma general no deberíamos tener problemas, podemos encontrarnos alguna situación en la que no funciona como debería.
Solución _spBodyOnLoadFunctionNames:
SharePoint utiliza sus propias funciones de carga y, en este caso vamos a aprovechar la función que se ejecuta en la carga del body, _spBodyOnLoadFunctionNames que se conjuntará con el código que usemos en el caso anterior. Para ello, sólo tendremos que hacer algo muy sencillo como es encapsular dentro de una función el código que queremos ejecutar al finalizar la carga de la página e instanciarlo con _spBodyOnLoadFunctionNames que lo pondrá en una cola de carga de scripts y que se ejecutar al finalizar todos los procesos de SharePoint
Es importante que intentemos hacer uso de las funciones que SharePoint nos provee y aprovechar así que la rueda ya está inventada, en vez de como casi siempre hacemos los amantes del desarrollo que es hacer nuestro propio código porque lo vemos más claro y, en ocasiones, incluso mejor. Un error que cometemos muy a menudo.
Hace ya algún tiempo, aprovechamos el lanzamiento público de Windows 8 por parte de Microsoft para presentar la correspondiente aplicación de CompartiMOSS en la que tuve el gusto de colaborar. Sin duda, fue un rotundo éxito que nos hizo pensar más allá y proponer un rediseño de la revista para ayudar a los lectores a encontrar los contenidos que buscan. Por lo tanto, el siguiente paso que debíamos dar era diseñar un nuevo portal web que permitiera consumir los artículos individualmente, obtener información de los editores y, sobre todo que otros usuarios que aún no conocen la revista puedan encontrarla fácilmente desde los buscadores.
Una vez teníamos la idea en la mente, el siguiente paso me correspondió para presentar una propuesta de diseño que gustó a los directores de la revista y que se decidió implantar en SharePoint 2013, habéis leído bien, usamos la nueva versión de la plataforma de Microsoft, con lo que comenzó un divertido camino que me permitió jugar con las diferentes y nuevas opciones disponibles en SharePoint 2013 para aplicar el diseño del portal desde la creación de una Masterpage (página maestra) y los distintos Page Layouts (Plantillas de página) hasta los Display Templates (Plantillas para mostrar). Todo ello además, intentando hacer el máximo uso de HTML5, CSS3 y Javascript conjugando las nuevas tecnologías a nuestro alcance en materia de entornos web.
Al tiempo que aplicaba el Branding al sitio de SharePoint 2013, Alberto Díaz configuraba todo lo necesario para que el funcionamiento fuera el deseado y, además también insertaba los contenidos provistos por los directores Juan Carlos González, Gustavo Vélez y Fabián Imaz que trabajaban a un ritmo frenético para tenerlo todo listo. Finalmente, nos dio tiempo de lanzar el nuevo portal como regalo de reyes el día 6 de enero estrenando además el nuevo número de la revista en el que, además tuve el honor de escribir un artículo sobre la aplicación de Windows 8 de CompartiMOSS. El resultado podéis evaluarlo y opinar. Espero que os guste
Nuevo número de CompartiMOSS
Aplicación de Windows 8 de CompartiMOSS
Nuevo portal web de Com0partiMOSS
Antes de irme, me gustaría deciros que estéis atentos a las próximas novedades porque estamos que lo tiramos y pronto daremos nuevas sorpresas.
Supongamos que queremos cargar jQuery sólo cuando lo necesitamos, por ejemplo, si tenemos un Control de usuario, o una librería de funciones que hace uso de jQuery y no queremos depender de si el portal web en el que lo queremos incrustar ya ha realizado la carga de esta librería de javascript.
Solución:
Aunque es algo bastante sencillo, siempre tengo que buscarlo y cada vez que lo hago me encuentro soluciones “estrambóticas” que en vez de facilitar la vida, la complican más aún. Por eso, quería contribuir con la solución más eficaz a esta cuestión.
Comprobar si jQuery está cargado en nuestra página
Con un sencillo bloque condicional, podemos comprobar si jQuery está presente en nuestro entorno.
1:if(jQuery) {
2: alert('jQuery está cargado');
3: } else {
4: alert ('jQuery NO está cargado');
5: }
Cargar jQuery dinámicamente
Haciendo uso de Javascript, cargaremos la librería jQuery de forma dinámica en el caso de que no estuviera presente en el sistema. Para ello, modificamos un poco el bloque condicional anterior para quedarnos únicamente con la opción en caso de que no estuviera cargado jQuery previamente
Tras unas largas vacaciones y el período de vuelta al trabajo, vuelvo a la carga con el blog cargado de artículos que me parecen interesantes sobre las tecnologías de Microsoft con las que trabajo habitualmente. Así pues, una vez terminado un año 2012 cargado de participaciones en eventos de desarrollo o muy relacionados con este mundo, como la Tenerife Lan Party 2k12 (TLP2k12), el Megathon de Windows 8 y el Lanzamiento de Visual Studio 2012 entre otros y en los que he compartido muchos buenos momentos con los asistentes que me han ayudado a crecer, uno de mis propósitos para este nuevo año en el que hemos entrado y que tiene muy mala rima es el de consolidar mi participación en eventos junto a TenerifeDev y General de Software y seguir mejorando día a día gracias al gran “coach” que es Alberto Díaz y a los pedacitos de sabiduría que voy recogiendo de otros grandes colaboradores de la comunidad de desarrolladores.
Además, este año se presenta cargado de trabajo (y eso que acabamos de empezarlo) debido a la actualización de productos y tecnologías de Microsoft, sobre todo la incorporación de HTML5 con Windows 8 y SharePoint 2013, por lo que escribiré bastante a menudo sobre Javascript agggggg $##@@~$%, ese gran lenguaje rescatado de la ultratumba , con lo que espero poder aportar mi granito de arena y ayudar a aquellos que buscan información en la red para resolver dudas o encontrar trucos que den respuesta a sus inquietudes.
Bueno, no me extenderé más en este artículo y, sin más preámbulos, doy el pistoletazo de salida a este año 2013
En Windows 8, la gran mayoría de las aplicaciones se alimentan de contenido en internet y, por ello, deben hacer cargas de datos iniciales desde la red, como en aplicaciones de noticias, que podemos gestionar de diferentes formas más o menos elegantes.
Abrir la aplicación vacía de datos y, en la página principal realizar la carga de contenido desde internet.
En este caso, se mostraría al usuario una página inicial "vacía" y se debería notificar al usuario que se están cargando los datos que, en muchos casos no deberían ser mostrados hasta la finalización de la carga de los mismos. Esto produciría un efecto muy feo de "Vacío-Lleno" además de que en las guías de diseño que ha realizado Microsoft, no se recomienda esta opción porque no da buena imagen mostrar la aplicación en su "esqueleto".
Abrir la aplicación con datos almacenados de anteriores ejecuciones, es decir, datos antiguos "cacheados".
Presenta un paradigma similar al anterior en el que, al mostrar la página inicial al usuario, habría que notificarle que se están cargando los datos pero, tendremos un problema mayor, dado que mientras se cargan los datos actuales el usuario podría interactuar con los datos antiguos, lo que podría provocar conflictos en la mayoría de los casos porque estará accediendo a las colecciones de datos mientras éstas se están actualizando. Una opción para salvar este problema sería bloquear la pantalla al usuario pero volvemos a entrar en conflicto con las recomendaciones que Microsoft indica en sus guías de diseño que, además, indican que no se debe bloquear la pantalla al usuario salvo necesidad imperativa.
Extender la Splash Screen para realizar la carga de datos.
Finalmente, la opción más elegante que además nos permitirá iniciar la aplicación datos y que éstos además sean los actuales, es extender la Splash Screen de nuestra aplicación mediante una "Extended Splash Screen" y que sea esta la que se encargue de cargar los datos a la vez que notifica al usuario el proceso. De esta forma, al terminar la carga de datos, la aplicación presentaría la página inicial de la aplicación al usuario con los datos actuales.
Una vez que tenemos claro que la mejor opción y la más elegante es el uso de una "Extended Splash Screen", tenemos que programarla correctamente, lo que no es algo trivial y que requiere editar más archivos de lo que a priori parecería.
Paso 1: Crear una nueva vista que he llamado ExtendedSplash y que servirá para realizar la carga de los datos. Esta vista sólo debe contener este "Grid" en el código XAML y no ser parte de una etiqueta "<Page>" ni "<commo:LayoutAwarePage>", es decir, al crearla, eliminamos todo el contenido XAML que contiene y ponemos este Grid que contiene, la imagen de SplashScreen que deberá ser puesta tal cual aparece en el ejemplo para que no haya diferencia con la vista anterior y además, he añadido otro Grid con un "ProgressRing" que indicará que hay un proceso en ejecución y un "TextBlock" con el texto "Cargando datos". Estos dos últimos elementos sí pueden ser modificados a nuestro gusto.
Paso 2: Una vez tengamos la vista creada, debemos indicarle a la aplicación que la navegación inicial la haga hacia nuestra Extended Splash Screen y no a la vista principal de la aplicación que teníamos anteriormente. Para ello debemos identificar el bloque condicional if (rootFrame.Content == null)y ponerlo como indico a continuación.
ExtendedSplash extendedSplash = new ExtendedSplash(args.SplashScreen, loadState);
Window.Current.Content = extendedSplash;
}
Paso 3: En este momento, nuestra aplicación ya será capaz de navegar a la Extended Splash Screen pero ésta de momento no hace nada, por lo que es hora de añadir el código necesario para la carga de los datos y que posteriormente continúe con la ejecución de la aplicación de forma normal en la que queremos que sea la vista inicial de nuestra aplicación. Para ello, el archivo de Code Behind debería quedar similar al ejemplo que sigue.
partial class ExtendedSplash
{
internal Rect splashImageRect; // Almacena las coordenadas de la imagen.
internalbool dismissed = false; // Control del estado de finalización.
internal Frame rootFrame;
private SplashScreen splash; // Variable to hold the splash screen object.
public ExtendedSplash(SplashScreen splashscreen, bool loadState)
{
InitializeComponent();
// Escucha los eventos de redimensionamiento de la vista para reposicionar la Extended Splash Screen
// Importante para asegurarnos que la vista responde bien ante los diferentes estados (Snapped, Portrait, Fill)
Window.Current.SizeChanged += new WindowSizeChangedEventHandler(ExtendedSplash_OnResize);
splash = splashscreen;
if (splash != null)
{
// Registra un manejador de eventos que se ejecutará cuando la SplashScreen haya sido finalizada
splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);
// Recupera las coordenadas de la imagen
splashImageRect = splash.ImageLocation;
}
// Se crea un frame que actúa como context de naveigación
Para que no extrañéis y por comodidad para el ejemplo, he establecido una propiedad estática en App.xaml.cs llamada App.SampleDataGroup donde almaceno los datos que he cargado para que puedan ser usados posteriormente en la vista principal de la aplicación. Si siguiéramos una estructura MVVM estricta esto se debería resolver con buenas artes.
Paso 4: Ya nos encontramos en el último paso del proceso de carga de datos que, por fin es mostrárselos al usuario y, para esto, tenemos que cambiar unas poquitas cosas en la vista principal de la aplicación. Lo primero es declarar una variable "Dismissed" y un método público para establecer su valor. Si os habéis fijado con detenimiento, os daréis cuenta que este método se usa en la Extended Splash Screen para notificar su finalización de carga. En principio no es necesario hacer nada con esta variable, pero podría sernos de utilidad en algunos casos.
En Segundo lugar, los datos ya no se van a cargar en la vista principal, sino que cuando la aplicación llegue aquí, los datos ya deberían estar cargados donde hayamos indicado y, en este caso, yo lo he almacenado por comodidad en App.SampleDataGroup, por lo que el evento LoadState de esta vista quedaría así.
Conclusión: Tal y como nos recomienda Microsoft, las aplicaciones tienen que ofrecer los datos lo más rápidamente posible o, al menos, notificar que se están obteniendo dado que nuestras aplicaciones deben ser "Fast & Fluid". Con las Extended Splash Screens podemos paliar el efecto de carga de datos permitiendo que el usuario sea consciente del proceso que se está ejecutando. Además, es importante tener en cuenta que si nuestras aplicaciones superan los 5 segundos pausadas en la SplashScreen por defecto, porque estemos haciendo carga de datos, Microsoft no nos va a certificar la aplicación por falta de rendimiento, por lo que en esos caso, el uso de una Extended Splash Screen se hace absolutamente necesario.
Podéis descargaros una aplicación que hace uso de la plantilla "Aplicación de cuadrícula (Grid App)" con el código de ejemplo para verlo en ejecución.