Mostrando entradas con la etiqueta windows 8. Mostrar todas las entradas
Mostrando entradas con la etiqueta windows 8. Mostrar todas las entradas

martes, 31 de julio de 2012

GridView, mostrando datos en tiempo de diseño

Algo que puede resulta molesto a la hora de trabajar con el GridView es que no vemos el aspecto que éste tendrá hasta que no ejecutamos la aplicación. Esto puede suponer una gran perdida de tiempo si estamos en una fase en la que estamos "depurando" nuestra UI.

Para mostrar datos en el diseñador debemos declararlos en el XAML en vez a través de la propiedad DataContext. Esto es así porque el diseñador parsea el XAML pero no ejecuta el code-behind. Existen varias alternativas para conseguir esto, así que vamos a ver una de ellas. Lo primero que haremos será definir nuestro origen de datos
public class MenuModel
{
    public int IdMenu { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

public class MenuModelList : List<MenuModel>
{
    public MenuModelList()
    {
        this.Add(new MenuModel() { IdMenu = 1, Name = "Name 1", Description = "Description 1" });
        this.Add(new MenuModel() { IdMenu = 2, Name = "Name 2", Description = "Description 2" });
    }
}
Después declararemos este objeto como un recurso para que pueda referenciado por otros elementos de la siguiente manera
<Page.Resources>
    <local:MenuModelList x:Key="MenuListData"/>
    <CollectionViewSource x:Name="MenuListResource"
        Source="{StaticResource MenuListData}"/>        
</Page.Resources>
Y lo referenciaremos desde nuestro GridView de la siguiente forma
<GridView x:Name="GridViewMenu"
            HorizontalAlignment="Left" 
            Margin="19,70,0,0" 
            Grid.Row="1" 
            VerticalAlignment="Top" 
            SelectionMode="None"
            IsItemClickEnabled="True"                                                       
            ItemsSource="{Binding Source={StaticResource MenuListResource}}">

    <!-- Resto de información del GridView -->
</GridView>
De esta manera veremos nuestro GridView en tiempo de diseño de la siguiente manera

GridView en tiempo de diseño

El único inconveniente del modelo planteado anteriormente es que esos datos serán los mismos que se usarán cuando nuestra aplicación esté en ejecución. Si queremos usar otros datos en ejecución podemos optar por cambiar el origen de datos en el constructor de nuestro modelo en base a si estamos en tiempo de diseño o en tiempo de ejecución. Para conseguir esto podemos hacer los siguiente
public class MenuModelList : List<MenuModel> {
    public MenuModelList()
    {
        if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
            GetSampleData();
        else
            GetRealData();
    }

    private void GetSampleData()
    {
        this.Add(new MenuModel() { IdMenu = 1, Name = "Name 1", Description = "Description 1" });
        this.Add(new MenuModel() { IdMenu = 2, Name = "Name 2", Description = "Description 2" });
    }

    private void GetRealData()
    {
        this.Add(new MenuModel() { IdMenu = 1, Name = "Elemento 1", Description = "Descripción del elemento 1" });
        this.Add(new MenuModel() { IdMenu = 2, Name = "Elemento 2", Description = "Descripción del elemento 2" });
    }
}
Si ejecutamos ahora nuestra aplicaciones veremos que obtenemos otros datos distintos a los que obteníamos en tiempo de diseño.

GridView en tiempo de ejecución

Como vemos es relativamente fácil mostrar información en nuestros GridView en tiempo de ejecución lo cual hace que el diseño de nuestra aplicación sea más fácil de llevar a cabo porque evitaremos infinidad de ejecuciones innecesarias.

Happy coding!

viernes, 27 de julio de 2012

Diferencias entre DataContext y ItemsSource en Metro

Para aquellos que no tengamos demasiada experiencia en WPF o Silverlight el bindeo de datos puede ser un poco confuso teniendo en cuenta que parece que se puede hacer de dos maneras distintas, tanto a través de la propiedad DataContext como de la propiedad ItemsSource. Pese a que puedan parecer propiedades idénticas nada más lejos de la realidad ya que ambas propiedades tienen un propósito bien distinto.

DataContext es una propiedad general de todos los descendientes de FrameworkElement. Es heredada a de padres a hijos y puede ser usada como origen de datos para el DataBinding.

ItemsSource es una propiedad que identifica la generación de elementos de los controles que derivan de ItemsControl. Cuando establecemos esta propiedad a través de DataBinding o vía código el control generará los elementos internamente. Estableciendo la propiedad DataContext en un ItemsControls no provocaremos el mismo efecto.

Bien, pero como no sólo de teoría vive el desarrollador vamos a ver esto en un ejemplo. Imaginemos que tenemos esta clase
public class MenuModel
{
    public int IdMenu { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}
Y que inicializamos una lista de elementos de la siguiente manera
List<MenuModel> items = new List<MenuModel>();
items.Add(new MenuModel() { IdMenu = 1, Name = "Elemento 1", Description = "Descripción del elemento 1" });
items.Add(new MenuModel() { IdMenu = 2, Name = "Elemento 2", Description = "Descripción del elemento 2" });
Bien con esto podremos hacer lo siguiente sobre un GridView
GridViewMenu.ItemsSource = items;
O sea, aplicaremos como origen de datos la colección de elementos única y exclusivamente al GridView. El resultado será este

GridView

Bien, ahora cambiaremos la llamada a ItemsSource por DataContext y veremos que ocurre. Correcto, lo que ocurre es que no se ha generado el GridView y eso porque el ItemsSource si lanza la generación del control pero el DataContext no. Para que se genere el control debemos modificar el DataBind del GridView  de la siguiente manera
<GridView x:Name="GridViewMenu"
            HorizontalAlignment="Left"
            Margin="19,70,0,0"
            Grid.Row="1"
            VerticalAlignment="Top"
            SelectionMode="None"
            IsItemClickEnabled="True"
            ItemTemplate="{StaticResource itemTemplate}"
            ItemsSource="{Binding}">

Bien, pero con DataContext podemos hacer algunas cosas más como hemos comentado antes. Vamos a crear un modelo que tenga nuestra lista de elemento y un texto y vamos a ver como podemos hacer el bindeo de datos de una manera muy simple.
public class MainPageModel
{
    public string Titulo { get; set; }
    public List<MenuModel> Items { get; set; }

    public MainPageModel()
    {
        this.Titulo = "Mi título";

        Items = new List<MenuModel>();
        Items.Add(new MenuModel() { IdMenu = 1, Name = "Elemento 1", Description = "Descripción del elemento 1" });
        Items.Add(new MenuModel() { IdMenu = 2, Name = "Elemento 2", Description = "Descripción del elemento 2" });
    }
}
Como hemos dicho antes DataContext es una propiedad que se programa por toda la jerarquía de hijos, así que la asignaremos al DataContext de la página
this.DataContext = model;
Y en el diseñador pondremos también un TextBox de la siguiente manera
<TextBlock HorizontalAlignment="Left" Height="24" Margin="18,16,0,0" Grid.Row="1" TextWrapping="Wrap" Text="{Binding Titulo}" FontSize="24" VerticalAlignment="Top" Width="339"/>
<GridView x:Name="GridViewMenu"
            HorizontalAlignment="Left"
            Margin="19,70,0,0"
            Grid.Row="1"
            VerticalAlignment="Top"
            SelectionMode="None"
            IsItemClickEnabled="True"
            ItemTemplate="{StaticResource itemTemplate}"
            ItemsSource="{Binding Items}">
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
El resultado de esto es el siguiente

GridView

En lineas generales podemos decir que usaremos ItemsSource si solo vamos a enlazar un ItemsControl con un único origen de datos y si tenemos varios elementos que van consumir nuestro origen de datos usaremos DataContext.

Nota: En el fichero StandardStyles.xaml tengo definida la siguiente Template para definir es aspecto del GridView
<!-- DataTemplates -->
<DataTemplate x:Key="itemTemplate">
    <Grid Background="DarkGray" Width="250" Height="250">
        <StackPanel Orientation="Vertical" VerticalAlignment="Bottom" Margin="0,0,0,10">
            <TextBlock Text="{Binding Name}" 
                    FontSize="24"  Margin="10,0,0,0" 
                    TextTrimming="WordEllipsis" TextWrapping="Wrap" 
                    HorizontalAlignment="Left"/>
            <TextBlock Text="{Binding Description}" 
                    FontSize="12" Margin="10,0,0,0" 
                    TextTrimming="WordEllipsis" TextWrapping="Wrap" 
                    HorizontalAlignment="Left"/>
        </StackPanel>
    </Grid>
</DataTemplate>

Happy coding!

martes, 24 de julio de 2012

Controles comunes en aplicaciones Metro

Desde hace un par de días estoy iniciándome en el desarrollo de aplicaciones Metro para Windows 8. Una vez instalado Windows 8 Release Preview y el Visual Studio 2012 RC tenemos todo lo necesario para comenzar con el desarrollo de este tipo de aplicaciones.

Una vez arrancado el Visual Studio seleccionaremos la plantilla Windows Metro Style en el lenguaje que más nos guste tal y como se muestra en la imagen


Tras esto se nos creará un proyecto de éste tipo con el siguiente aspecto


En este primer artículo voy a hablar un poco de los controles que tenemos a nuestra disposición para desarrollar para Metro ya que la lista puede agobiar un poco al principio, o al menos esa fue mi primera impresión ya que siempre he trabajado para aplicaciones web o como mucho alguna aplicación de escritorio de tipo WinForms y nunca he hecho nada serio para WPF o Silverlight.

Controles más comunes
  • Border: Dibuja un borde, un fondo o ambos alrededor de un objeto.
<Border BorderBrush="Black" BorderThickness="1" 
        Height="120" Width="60">
    <StackPanel>
        <Rectangle Fill="Red"/>
        <Rectangle Fill="Green"/>
    </StackPanel>
</Border>
  • Button: Representa un control de tipo botón que interpreta un click del usuario.
<Button .../>
-or-
<Button>
    singleObject
</Button>
-or-
<Button ...>stringContent</Button>
  • CheckBox: Representa un control que el usuario puede marcar (check) o desmarcar (uncheck). Este control también puede tener un valor indeterminado.
<CheckBox .../>
-or-
<CheckBox>
  singleObject
</CheckBox>
-or-
<CheckBox>stringContent</CheckBox>
  • ComboBox: Control de selección que combina un textbox no editable y un drop-down list que permite al usuario seleccionar un elemento de una lista.
<ComboBox x:Name="ComboColores" Height="20" Width="150" ItemsSource="{Binding}" />
ObservableCollection<string> colores = new ObservableCollection<string>();
colores.Add("Rojo");
colores.Add("Verde");
colores.Add("Azul");
     
ComboColores.DataContext = colores;
  • FlipView: Representa un control para mostrar elementos, pero que muestra un elemento cada vez, y tiene un comportamiento de "flip" cuando se pasa de uno a otro.
Control FlipView usado para mostrar una galería de imágenes
  • Grid: Define un área flexible organizada en filas y columnas. Los elementos hijos son organizados en base a la cantidad de filas y columnas definidas.
  • GridView: Muestra un Grid horizontal de elementos de datos.
Metro GridView
  • Image: Control que muestra una imagen. La imagen puede estar en varios formatos (Joint Photographic Experts Group [JPEG], Portable Network Graphics [PNG], Bitmap [BMP], Graphics Interchange Format [GIF], Tagged Image File Format [TIFF], JPEG XR, icons [ICO]).
  • ListView: Muestra una lista de elementos de manera vertical.
Metro ListView
  • RadioButton: Le permite al usuario seleccionar una opción de un grupo de opciones.
  • StackPanel: Organiza una lista de elementos hijo en una única fila que puede ser orientada de manera vertical u horizontal.
  • <StackPanel x:Name="MyStackPanel">
      <TextBlock x:Name="TextFirstName" Text="Nombre" Width="75" HorizontalAlignment="Left"/>
      <TextBlock x:Name="TextLastName" Text="Apellidos" Width="75" HorizontalAlignment="Left"/>
      <TextBlock x:Name="TextAddress" Text="Dirección" Width="150" HorizontalAlignment="Left"/>
    </StackPanel>
  • TextBlock: Control que nos ayuda a mostrar una pequeña cantidad de texto.
<TextBlock ...>text</TextBlock>
-or-
<TextBlock>
  oneOrMoreInlineElements
</TextBlock>
-or-
<TextBlock .../>
Otros controles que nos pueden ser útiles
  • AppBar: Representa un control contenedor que contiene los componentes de interfaz de usuario para ejecutar acciones.
Metro AppBar
  • Canvas: Define un área en la que pueden colocarse explícitamente objetos, usando coordenadas que son relativas al "Canvas".
<Canvas Width="640" Height="480" >
    <Rectangle Canvas.Left="30" Canvas.Top="30" 
       Fill="Red" Width="200" Height="200" />
</Canvas>
  • Frame: Representa un control de contenido que soporta la navegación.
  • MediaElement: Representa un objeto que contiene audio, vídeo o ambos.
<MediaElement Source="Media/video1.mp4" AutoPlay="True" />
  • SemanticZoom: Representa un control con scroll que contiene dos vistas que tienen una relación semántica.
<SemanticZoom ...>
  <SemanticZoom.ZoomedOutView>
    zoomedOutViewContent
  </SemanticZoom.ZoomedOutView>
  <SemanticZoom.ZoomedInView>
    zoomedInViewContent
  </SemanticZoom.ZoomedInView>
</SemanticZoom>
Metro SemanticZoom
Metro SemanticZoom
  • Slider: Representa un control que permite al usuario seleccionar un valor dentro de un rango.
Metro Slider
Con esto acabamos la introducción a los controles que tenemos a nuestra disposición en la aplicaciones Metro. En los próximos artículos iremos viendo como utilizarlos dentro de nuestras aplicaciones.


Happy coding!