jueves, 16 de agosto de 2012

Disponible Visual Studio 2012



Desde hoy se encuentra disponible para la descarga de subscriptores a MSDN la nueva versión de Visual Studio 2012 que como ya hemos comentado antes en anteriores entradas tiene incluido LightSwitch.

Esta nueva versión incluye una gran variedad de mejoras como un nuevo tema por defecto, más moderno y en linea con el estilo Metro de Microsoft, acceso y publicación de datos en formato OData, integración con Active Directory, nuevos tipos de datos de negocio y muchas cosas más. También están trabajando en un cliente HTML que estará disponible como un complemento para Visual Studio 2012 muy pronto.

Podéis encontrar más detalles sobre este lanzamiento y los recursos disponibles en el blog del equipo de LightSwitch.

jueves, 9 de agosto de 2012

Creación dinámica de nombres de columnas en una rejilla editable

LightSwitch nos da la capacidad de importar datos de numerosas fuentes. Estos datos se pueden mostrar al usuario final en una rejilla editable (grid) por la simple creación de pantallas de tipo rejilla editable.

Los nombres de las columnas de la rejilla se corresponden con los nombres de los campos de la tabla que importamos. Esto funciona para la mayoría de los casos, pero en ciertas situaciones se necesita que estos nombres sean dinámicos. Por ejemplo, considera una aplicación para el Top 5 de coches del año con la base de datos diseñada de la siguiente manera:

CarRating
AttributeName
Car1
Car2
Car3
Car4
Car5
Frenado
Bueno
Muy bueno
Bueno
Bueno
Bueno
Aceleración
Excelente
Malo
Muy bueno
Muy bueno
Bueno
Velocidad
Excelente
Excelente
Muy bueno
Bueno
Malo
Manipulación
Muy bueno
Excelente
Malo
Malo
Bueno
Car
Name
Ranking
BMW
5
Mercedes
4
Porsche
3
Aston Martin
2
Ferrari
1

Ahora queremos mostrar la tabla de clasificación de coches pero en lugar de "Car1", Car2 ", etc..., en nuestros nombres de las columnas queremos leer de la tabla "Car", obtener los 5 mejores coches y sustituir los nombres de las columnas con los nombres que se obtienen de la tabla.

Con el fin de hacer eso, empezaremos con la creación de las 2 tablas anteriores: CarRating y Car. CarRating tendrá campos de tipo cadena llamados AttributeName, Car1, Car2, Car3, Car4 y Car5. La tabla Car tendrá un campo de tipo cadena llamado Name y un campo tipo entero denominado Ranking.

Aquí está la imagen de las tablas tal como se ve en LightSwitch:



A continuación, creamos una pantalla de tipo rejilla para CarRating. Así que haz clic con el boton derecho en el nodo de pantallas desde el Explorador de Soluciones y despues haz clic en Agregar pantalla. Selecciona la plantilla de rejilla editable y selecciona CarRatings como origen de datos y el nombre CarRatingsGridScreen.

Ahora desde el Explorador de Soluciones, haz clic en el CarRatingsGridScreen y selecciona Ver código de pantalla.

Esto te llevará al editor de código. Reemplaza todo el código con lo siguiente (asegúrate de que el nombre de espacio de nombres es coherente con el resto de los archivos de código de usuario):

VB
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.LightSwitch
Imports Microsoft.LightSwitch.Presentation
Imports Microsoft.LightSwitch.Presentation.Extensions
Imports System.Windows.Controls
Imports Microsoft.LightSwitch.Threading
Namespace LightSwitchApplication
    Partial Public Class CarRatingsGridScreen

        Private Sub CarRatingsGridScreen_Created()
            AddHandler Me.FindControl("grid").ControlAvailable, AddressOf CarRatingsGrid_ControlAvailable
        End Sub

        Private Sub CarRatingsGrid_ControlAvailable(sender As Object, e As ControlAvailableEventArgs)
            UpdateColumnNames(DirectCast(e.Control, DataGrid))
        End Sub

        Private Sub UpdateColumnNames(carRatingsGrid As DataGrid)
            Me.Details.Dispatcher.BeginInvoke(
                Sub()

                    Dim top5Cars = Me.DataWorkspace.ApplicationData.Cars.OrderBy(Function(car) car.Ranking).Take(5).Execute()

                    Dim carNames As String() = top5Cars.[Select](Function(car) car.Name).ToArray()

                    Dispatchers.Main.BeginInvoke(
                        Sub()
                            Dim rowTemplate As IContentItem = DirectCast(carRatingsGrid.DataContext, IContentItem).ChildItems(0)

                            For index As Integer = 0 To carNames.Length - 1
                                'start with the second column of the grid
                                rowTemplate.ChildItems(index + 1).DisplayName = carNames(index)
                            Next

                        End Sub)

                End Sub)
        End Sub
    End Class
End Namespace

C#
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Presentation;
using Microsoft.LightSwitch.Presentation.Extensions;
using System.Windows.Controls;
using Microsoft.LightSwitch.Threading;
namespace LightSwitchApplication
{
    public partial class CarRatingsGridScreen
    {
        partial void CarRatingsGridScreen_Created()
        {
            this.FindControl("grid").ControlAvailable += CarRatingsGrid_ControlAvailable;
        }

        void CarRatingsGrid_ControlAvailable(object sender, ControlAvailableEventArgs e)
        {            
            UpdateColumnNames((DataGrid)e.Control);
        }

        private void UpdateColumnNames(DataGrid carRatingsGrid)
        {
            this.Details.Dispatcher.BeginInvoke(() =>
            {                

                var top5Cars = this.DataWorkspace.ApplicationData.Cars.OrderBy(car => car.Ranking).Take(5).Execute();
                
                string[] carNames = top5Cars.Select(car => car.Name).ToArray();

                Dispatchers.Main.BeginInvoke(() =>
                {
                    IContentItem rowTemplate = ((IContentItem)carRatingsGrid.DataContext).ChildItems[0];
                                        
                    for (int index = 0; index < carNames.Length; index++)
                    {
                        //start with the second column of the grid
                        rowTemplate.ChildItems[index + 1].DisplayName = carNames[index];
                    }
                });
            });
        }
    }
}

En el código anterior, lo primero que estamos haciendo es el registro de controlador de eventos con el evento CarRatingsGrid_ControlAvailable de nuestro DataGrid. Esto está ocurriendo en el método CarRatingsGridScreen_Created.

Cuando la rejilla de datos en la pantalla aparece, nuestro método CarRatingsGrid_ControlAvailable se disparará. Este método tiene un argumento de tipo ControlAvailableEventArgs desde la cual podemos obtener el control real de Silverlight.

A continuación pasamos el control al método UpdateColumnNames desde CarRatingsGrid_ControlAvailable. Dado que el método se ejecuta en el subproceso principal, vamos al hilo lógico para obtener los 5 primeros nombres de coches y almacenarlos en una matriz (no podemos acceder a los datos del DataWorkspace en el hilo principal). Entonces volvemos al hilo principal y establecemos los nombres de columnas en la rejilla.

Ahora bien, para comprobar que funciona, tendremos que agregar unos cuantos registros en la tabla "Car". Así que crearemos una pantalla de rejilla editable para la tabla de coches y añadiremos unos pocos registros. Despues abre una nueva instancia de la CarRatingsGridScreen, debe tener los nombres de las columnas actualizadas.

Aquí está una captura de cómo deben ser las las pantallas en tiempo de ejecución:



A pesar de este post es sobre la configuración de los nombres de las columnas de forma dinámica, se puede extender a cualquier tipo de manipulación del interfaz de usuario. Por ejemplo, podemos obtener un identificador para un control de cuadro de texto en una pantalla y establecer su fondo en amarillo sobre la base de un cálculo, o podemos cambiar el color de la fuente de una celda de la rejilla de datos. El mismo concepto se aplica - obtener un identificador para el control de Silverlight subyacente y cambiar cualquier propiedad que deseemos en el proceso del interfaz de usuario.

Este texto es una traducción de un articulo original del Babar Ismail Dynamically setting column names on an editable grid.