Etiquetado: XAML

Inhabilitar la transición de entrada para algunos controles del Grid XAML

Las animaciones de entrada, salida, añadir elemento, seleccionar, ordenar, etc., que trae el SDK de la Tienda Windows aportan un toque de calidad a nuestras apps. Las páginas que creamos desde Visual Studio incorporan algunas transiciones por defecto, aunque en algunas ocasiones nos interesará inhabilitarlas.

Eliminar las transiciones de entrada de un Grid es sencillo, sólo tendremos que borrar la colección de transiciones que ya nos habrá añadido el SDK en la página y, por si acaso, asegurarnos que no queda ninguna:

Sigue leyendo

Anuncios

Caché HTTP de cliente en C# (1 de 4): aplicaciones de escritorio

Hoy en día es muy habitual utilizar contenido web en nuestras aplicaciones y eso penaliza el rendimiento. Para mejorarlo vamos a tener que almacenar en caché dicho contenido. Hacerlo bien no es difícil, pero es necesario conocer cómo funcionan los mecanismos de caché en la web y buscar dentro de la documentación de .Net cómo podemos aprovechar estos.

Upload / Download
Upload / Download por johntrainor, en Flickr

Como no soy el primero en tener la necesidad, existen algunas entradas en StackOverflow sobre el tema. Parece que la solución propuesta funciona bien, pero todas los que he visto se olvidan de algunos puntos importantes, como por ejemplo pedir al servidor si hay una versión actualizada del archivo, añadir técnicas de scavenging para que el contenido descargado caduque, etc. Además se olvidan de que el sistema operativo ya sabe cachear y es un poco raro que tengamos que volver a programar el caché que tan bien hacen los navegadores.

Te recomiendo leer el artículo hasta el final, pero si tienes mucha prisa puedes descargar el código de ejemplo en GitHub.

Sigue leyendo

Importar estilos XAML en otro proyecto Windows Store

Si queremos compartir los estilos entre diferentes librerías en las aplicaciones de Windows Store debemos tener en cuenta que los estilos no estarán embebidos dentro de la librería tal como ocurre en las aplicaciones WPF, sino que se guarda el XAML dentro de una carpeta con el nombre de la librería. Esta diferencia implica que el enlace al XAML no será igual.

Así, si nuestra librería referenciada es MiLibreria.Estilos y tenemos el estilo en el raíz, deberemos escribir el ResourceDictionary de la siguiente manera:

<ResourceDictionary Source="ms-appx:///MiLibreria.Estilos/StandardStyles.xaml"/>

Es fácil de comprobar, pues al compilar nuestro proyecto veremos como dentro de nuestra carpeta de compilación se crea una carpeta para la librería referenciada que contiene los archivos XAML.

Binding a imágenes de carpetas especiales en Windows 8

Descarga el código de este artículo en Codeplex

Hoy para cambiar un poco haré un ejemplo en XAML/C#, pero seguimos con aplicaciones de la tienda Windows.
Os explicaré un truco que se puede realizar de dos formas: la primera, la forma automática, utilizando una clase del sistema que ya nos hace casi todo el trabajo y la segunda, una forma manual de realizarlo, que dejaremos para más adelante.

Las carpetas especiales

En las aplicaciones de la Tienda Windows podemos acceder directamente a algunas carpetas especiales del sistema siempre que declaremos en el manifiesto que queremos acceder y el usuario lo sepa:
pictureslibrary
Una vez hemos establecido el requisito en el manifiesto, ya podemos utilizar la clase Windows.Storage.KnownFolders para listar los elementos de la carpeta de imágenes:

var queryOptions = new Windows.Storage.Search.QueryOptions();
queryOptions.FolderDepth = FolderDepth.Deep;
var query = KnownFolders.PicturesLibrary.CreateFileQueryWithOptions(queryOptions);

Nota: si intentáis esto en otra carpeta, como por ejemplo “Mis Documentos”, no funcionará, pues también hay que declarar que tipos de archivo vamos a abrir y sólo podremos abrir esos.

Listar todos los archivos dentro de la carpeta

Para obtener una lista de todos los archivos podemos llamar al método GetFilesAsync() y luego podremos trabajar sobre la misma. Si vamos a representar esa lista en el interfaz de usuario, WinRT nos ofrece una forma mucho mejor: podemos obtener una lista virtualizada, esto es, una lista con el mismo número de elementos que contiene la carpeta y las características de esos elementos se van obteniendo de forma asíncrona. De esta forma obtendremos los primeros resultados mucho más rápido y veremos en nuestra colección en pantalla el tamaño completo de la lista, aunque todavía no se hayan obtenido todos los resultados.

public class DataSource:INotifyPropertyChanged
{
    object _items;
    public object Items
    {
        get { return _items; }
        private set
        {
            _items = value;
            onPropertyChanged("Items");
        }
    }

    public DataSource()
    {
        try
        {
            var queryOptions = new Windows.Storage.Search.QueryOptions();
            queryOptions.FolderDepth = FolderDepth.Deep;
            var query = KnownFolders.PicturesLibrary.CreateFileQueryWithOptions(queryOptions);
            var fileInformationFactory = new FileInformationFactory(query,
                Windows.Storage.FileProperties.ThumbnailMode.PicturesView,
                150, Windows.Storage.FileProperties.ThumbnailOptions.UseCurrentScale, true);
            Items = fileInformationFactory.GetVirtualizedFilesVector();
        }
        catch (Exception ex)
        {
            Items = new object[] {new{ Name = ex.Message} };
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void onPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Si observamos el código, veremos que la clase FileInformationFactory nos permite generar también una vista previa de cada uno de los archivos. El método no es asíncrono, esto quiere decir que nos devolverá muy rápidamente un resultado: la lista virtualizada llena de elementos vacíos, que luego se irán rellenando en segundo plano.

Ahora sólo nos hace falta crear un contenedor GridView para mostrar los archivos:

<Page
    x:Class="ImageBinding.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ImageBinding"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:localData="using:ImageBinding.DataModel">
    <Page.Resources>
        <localData:DataSource x:Key="mainDataSource"></localData:DataSource>
        <CollectionViewSource Source="{Binding Path=Items, Source={StaticResource mainDataSource}}"
                              x:Key="mainView"></CollectionViewSource>
        <DataTemplate x:Key="DataTemplate">
            <Grid Width="150">
                <TextBlock Text="{Binding Name}" TextTrimming="WordEllipsis" ></TextBlock>
            </Grid>
        </DataTemplate>
    </Page.Resources>
    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" 
        DataContext="{StaticResource mainDataSource}">
        <GridView
            Margin="0 90 0 0" ItemsSource="{Binding Source={StaticResource mainView }}" 
                  ItemTemplate="{StaticResource DataTemplate}" SelectionMode="None">
        </GridView>
    </Grid>
</Page>

Carga de imágenes

Una vez tenemos la lista de archivos vamos a mostrar las imágenes que os prometí al principio del artículo. La colección que nos proporciona FileInformationFactory.GetVirtualizedFilesVector() contiene elementos que cumplen con el interfaz IStorageItemInformation. Estos elementos tienen una propiedad Thumbnail a la que podremos enlazarnos para visualizar la imagen, pero no podremos hacerlo directamente pues el tipo StorageItemThumbnail en realidad es un tipo Stream y no una imagen, así que necesitaremos un Converter para poder utilizar la imagen dentro del interfaz de usuario:

public class StreamToBitmapConverter:IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value != null)
        {
            var stream = (IRandomAccessStream)value;
            var img = new BitmapImage();
            img.SetSource(stream);
            return img;
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

A través del Converter ya podremos hacer el enlace correctamente:

<Page.Resources>
    <localData:DataSource x:Key="mainDataSource"></localData:DataSource>
    <CollectionViewSource Source="{Binding Path=Items, Source={StaticResource mainDataSource}}"
                          x:Key="mainView"></CollectionViewSource>
    <localConverters:StreamToBitmapConverter x:Key="bitmapConverter"/>
    <DataTemplate x:Key="DataTemplate">
        <Grid Width="150">
            <Grid.RowDefinitions>
                <RowDefinition Height="70"/>
                <RowDefinition Height="32"/>    
            </Grid.RowDefinitions>
            <Image Grid.RowSpan="2" Source="{Binding Thumbnail, 
                Converter={StaticResource bitmapConverter}}"></Image>
            <Border Grid.Row="1" Background="#80000000" Padding="5">
                <TextBlock Text="{Binding Name}" VerticalAlignment="Center" 
                           TextTrimming="WordEllipsis" />
            </Border>
        </Grid>
    </DataTemplate>
</Page.Resources>

Y aquí tenemos el resultado:
picturesCollection
En el próximo artículo os contaré cómo hacer lo mismo pero programando nosotros la carga asíncrona de imágenes bajo demanda.

Descarga el código de este artículo en Codeplex

XAML Flyout y otras funcionalidades de UI en aplicaciones Metro

Si ya habéis empezado a desarrollar aplicaciones Metro y las estáis haciendo en XAML os habréis dado cuenta que todavía faltan algunos controles que habréis visto en algunas aplicaciones y demos, pues en la plataforma JavaScript ya los tenemos.
Mientras esperamos los controles oficiales, algunos desarrolladores han tenido la gentileza de compartir con los demás sus propios controles, aquí tenéis dos que he utilizado.

  • Tim Heuer nos proporciona la librería Callisto que nos permitirá añadir algunas funcionalidades que nos faltan en el framework de XAML que viene para las aplicaciones Metro de Windows 8, como por ejemplo los elementos FlyOut: https://github.com/timheuer/callisto
  • Como en esa librería tampoco está todo, en Codeplex también tenemos el WinRT XAML Toolkit que contiene algunos elementos útiles como diálogos personalizables o un visor de estilos: http://winrtxamltoolkit.codeplex.com/

Espero que os sean tan útiles como a mí 🙂