Null World

Donde nada es lo que parece, especialmente los punteros

April 2009 - Artículos

Los secretos del casting

Y no estamos hablando de los castings de Operación Triunfo o Gran Hermano, no. Os propongo pasar la tarde de hoy pensando en una de esas cosas que no dejan de ser interesantes pese a servir para bastante poco ;)

Seguro que todos los días mientras programáis os encontráis con situaciones en las que tenéis que convertir objetos de un tipo a otro, lo que se conoce como un casting (que no tiene nada que ver con concursos, por suerte). En C# las dos formas más comunes de realizarlo son con un cast explicito o utilizando el operador as:

object o = new Concursante();
Concursante concursante;

concursante = (Concursante)o; //Explicito
concursante = o as Concursante; //Operador as

Visto esto ya no haré ningún comentario, y me limitare a lanzar mi pregunta. Basaros simplemente en lo que sabéis de ambas operaciones y en vuestra intuición vale? La pregunta es…cual de las dos formas de realizar un cast es más rápida?

La respuesta, en breve, en esta misma cadena…o no ;)


Rock Tip. Visto que todo lo que hemos tenido por el momento en estos rock tips ha sido música en inglés creo que por una vez, aprovechando el cambio de temática del post, podríamos buscar otro idioma…como el alemán. Hoy cierra el post Rammstein con una de sus mejores canciones (IMHO) acompañada de un gran videoclip: Ich Will. Enjoy!!

Publicado 29/4/2009 12:09 por Francisco Martinez | 9 comment(s)

Archivado en: ,

Un sencillo menú en WPF: Recursos (II)

Dado que en el post anterior hablábamos sobre estilos y plantillas, vamos a ver un poco mas en detalle ahora como podemos estructurarlos y acceder a ellos de la mejor manera posible. En el proyecto (adjunto en la primera parte) vemos que en la ruta /Themes/Default.xaml encontramos un diccionario de recursos.

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d">
    <!-- Resource dictionary entries should be defined here. -->
    <Style x:Key="ButtonFocusVisual">
        ...
    </Style>
    <LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
        ...
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
    <Style x:Key="MenuButtonStyle" TargetType="{x:Type Button}">
        ...
    </Style>
</ResourceDictionary>

Como podemos ver, este diccionario de recursos contiene estilos, plantillas, brochas y demás recursos que utilizaremos a lo largo de toda nuestra aplicación. Es imprescindible que todos ellos tengan un atributo x:Key para poder ser referenciados desde nuestros elementos de interfaz. Para ello, primero necesitamos agregar a nuestro App.xaml una referencia al diccionario (o diccionarios) de recursos que queramos emplear.

<Application.Resources>
    <!-- Resources scoped at the Application level should be defined here. -->
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Themes\Default.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Una vez hecho esto, solo necesitamos aplicar el recurso deseado mediante la extensión de marcado DynamicResource en la propiedad que nosotros elijamos:

<StackPanel x:Name="LayoutRoot" Width="600" Height="66">
    <StackPanel x:Name="ButtonStack" Width="Auto" Orientation="Horizontal" HorizontalAlignment="Right" Height="26" ButtonBase.Click="ButtonStack_Click">
        <Button Content="Home" x:Name="HomeButton" Width="70" Style="{DynamicResource MenuButtonStyle}" Height="24" MouseEnter="ButtonStack_MouseEnter"/>
        ...
    </StackPanel>

No es necesario que especifiquemos un path al recurso, como haríamos con un binding al uso, dado que automáticamente se buscará el recurso en los diccionarios de recursos cargados en ese momento cuando sea necesario mostrarlo. Esa es la diferencia entre DynamicResource y su hermana StaticResource: mientras que DynamicResource cargará el recurso en el momento en que se muestra el elemento que lo referencia, StaticResource realiza esa asignación en el momento en el que se carga XAML. Esto podemos aprovecharlo para cargar y modificar recursos en tiempo de ejecución, como veremos en un próximo post.

Otro punto interesante en este sencillo ejemplo de un menú es el acceso a recursos dentro de la plantilla aplicada a un elemento. En nuestro caso, la plantilla que aplicamos a nuestros botones define una Storyboard que queremos utilizar. La manera de hacerlo es la siguiente:

private void DoButtonMouseOver(Button origin)
{
    Storyboard mouseOver = (Storyboard)origin.Template.Resources["MouseOver"];
    mouseOver.Begin(origin, origin.Template);
}

Como vemos, necesitamos una referencia al objeto Button para acceder a los recursos de su plantilla y buscar la Storyboard que nos interesa, para después llamar a su método Begin. La particularidad aquí es que no es suficiente con pasarle como argumento el botón, puesto que la animación trabaja con objetos de la plantilla y no es capaz de encontrarlos, saludándonos con una bonita InvalidOperationException. Para ello existe una sobrecarga del método Begin que recibe tanto el elemento sobre el que se inicia la animación como la plantilla que la contiene.


Rock Tip. Siguiendo mi rutina habitual de añadir canciones sin ninguna relación con lo relatado, os presento hoy uno de los grupos que mejor capturan la esencia del Shock Rock abanderado por KISS, el conjunto liderado por Blackie Lawless W.A.S.P., con su canción (de genial videoclip) Wild Child. Enjoy!!

Publicado 22/4/2009 10:27 por Francisco Martinez | 1 comment(s)

Archivado en:

La nueva MSDN

O “Como obtener mas visitas en un blog gracias a un título levemente amarillista”. El caso es que no podemos hablar de una nueva MSDN, pero si de una nueva manera de acceder a su información de forma más sencilla y accesible. Microsoft mantiene diversas versiones de la MSDN para distintos soportes: dispositivos móviles, pantalla, impresión, etc. De un tiempo a esta parte se ha sumado una nueva versión “Low Bandwidth” creada para consumir menos ancho de banda. Para ello han eliminado gran cantidad de elementos pero intentando siempre mantener la información inalterable. El resultado? Una web mucho mas ligera y sencilla de consultar, como podéis comprobar vosotros mismos:

System.Object en la MSDN

System.Object en la MSDN Low Bandwidth

Para acceder a los artículos de MSDN de está forma solo tenéis que añadir a la URL la opción (loband) como en el segundo enlace, y además tendréis una opción en la esquina superior derecha de vuestras pantallas para establecerlo como modo por defecto.


Rock Tip. Danger Danger es un grupo de hard rock que por desgracia llego demasiado tarde, en esa triste época en la que aparecieron Nirvana y el grunge para acabar con todo lo bueno. Pese a todo, un grupo con un gran vocalista, un excelente guitarra y melodías muy pegadizas no puede quedar en el olvido (aunque de eso ya se encarga mi compañero Pablo Doval), así que rescatare para este post su clásico Rock America, que aunque suena bien en directo, suena mejor en un Corvette rojo descapotado…Enjoy!

Publicado 16/4/2009 12:05 por Francisco Martinez | 3 comment(s)

Archivado en: ,

Un sencillo menú en WPF: Estilos y Plantillas (I)

En el post anterior sobre la creación de un Motion Path desde Visual Studio, Julio Trujillo comentaba sobre la posibilidad de aplicar lo aprendido para la creación de un menú similar al de Silverlight.net. Lo que haremos será, en lugar de limitarnos a crear el menú, aprovecharlo para aprender alguna cosa nueva, en este caso, algo sobre estilos y plantillas.

Lo primero de todo es saber lo que es cada cosa. Un estilo (Style) no es mas que un conjunto de objetos de tipo Setter, pares de propiedad y valor, aplicados a los objetos de un tipo concreto. Es decir, un estilo nos permite definir un recurso compartido para mantener la coherencia de nuestra interfaz de usuario, abarcando tanto el aspecto visual (recursos, propiedades) como el comportamiento (triggers) de las instancias de un tipo concreto. Veámoslo con un ejemplo de nuestro proyecto.

    <Style x:Key="MenuButtonStyle" TargetType="{x:Type Button}">

<
Setter Property="HorizontalContentAlignment" Value="Center"/>
<
Setter Property="VerticalContentAlignment" Value="Center"/>
<
Setter Property="Padding" Value="1"/>
<
Setter Property="Template">
<
Setter.Value>
<
ControlTemplate TargetType="{x:Type Button}">
<
ControlTemplate.Resources>
<
Storyboard x:Key="MouseOver">…</Storyboard>
<
Storyboard x:Key="UnMouseOver">…</Storyboard>
<
Storyboard x:Key="Click">…</Storyboard>
<
Storyboard x:Key="UnClick">…</Storyboard>
</
ControlTemplate.Resources>
<
Grid x:Name="LayoutRoot">…</Grid>
</
ControlTemplate>
</
Setter.Value>
</
Setter>
</
Style>

Ahí podemos ver el estilo de los botones de nuestro menú (levemente editado para que no nos ocupe media página). Como vemos, le asignamos al estilo una clave (imprescindible para almacenarlo en un diccionario de recursos, como veremos después) y un tipo de destino, de manera que el estilo se aplicará automágicamente a todos los objetos de tipo Button. Además, establecemos las propiedades que queremos que compartan (alineación y padding entre otras) y la propiedad más interesante de todas: la plantilla (Template). Las plantillas controlan la estructura visual y el comportamiento de los controles en WPF, y son la clave de su flexibilidad a la hora de modificar el aspecto de nuestra aplicación. Si nos fijamos en el código anterior, dentro de la plantilla definimos una serie de recursos (storyboard) para su uso dentro de la misma, y le añadimos un Grid, con un contenido. En nuestro caso es el siguiente:

<Grid x:Name="LayoutRoot">
<
Rectangle Opacity="0" x:Name="MassiveGlow" StrokeThickness="0">
<
Rectangle.Fill>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<
GradientStop Color="#00FFFFFF" Offset="0"/>
<
GradientStop Color="#BEFFFFFF" Offset="0.74"/>
<
GradientStop Color="#00FFFFFF" Offset="1"/>
</
LinearGradientBrush>
</
Rectangle.Fill>
</
Rectangle>
<
Rectangle Opacity="0" x:Name="Glow" StrokeThickness="0">
<
Rectangle.Fill>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<
GradientStop Color="#00FFFFFF" Offset="0"/>
<
GradientStop Color="#7FFFFFFF" Offset="0.74"/>
<
GradientStop Color="#00FFFFFF" Offset="1"/>
</
LinearGradientBrush>
</
Rectangle.Fill>
</
Rectangle>
<
Rectangle Opacity="0.795" HorizontalAlignment="Left" x:Name="LeftSeparator"
Width="1" Fill="#FFFFFFFF" Stroke="#FFFFFFFF" StrokeThickness="1"/>
<
Rectangle Opacity="0.795" HorizontalAlignment="Right" x:Name="RightSeparator"
Width="1" Fill="#FFFFFFFF" Stroke="#FFFFFFFF"/>
<
TextBlock HorizontalAlignment="Center" x:Name="NameTextBlockShadow"
VerticalAlignment="Center" FontSize="14" Foreground="#FF000000"
TextWrapping="Wrap" d:LayoutOverrides="Height"
Text="{TemplateBinding Content}" Margin="2,2,0,0"/>
<
TextBlock HorizontalAlignment="Center" x:Name="NameTextBlock"
VerticalAlignment="Center" FontSize="14" Foreground="#FFFFFFFF"
Text="{TemplateBinding Content}" TextWrapping="Wrap"/>
</
Grid>

Como podemos ver, dentro de ese Grid estamos redefiniendo por completo el aspecto visual de nuestro botón. Creamos dos rectángulos con un brillo para hacer efectos cuando el botón sea seleccionado, otros dos rectángulos como separadores laterales, y dos bloques de texto para el contenido del botón. Ya hemos visto como cambiar el aspecto visual de un elemento editando su estilo y su plantilla, y en el próximo post veremos como trabajar cómodamente con los recursos de nuestra aplicación.

 


 

Rock Tip. Aunque es muy común que un grupo musical realice versiones de otros temas adaptándolos con mayor o menor acierto a su estilo, no es tan común que un grupo metal, como los impactantes Turisas, se dedique a versionar a un grupo disco, como Boney M. Sin embargo, como de cambio de estilos precisamente estamos hablando, me parece mas que interesante resaltar este Rasputin. Enjoy!

Publicado 15/4/2009 10:53 por Francisco Martinez | 7 comment(s)

Archivado en:

Creando un Motion Path desde Visual Studio

En el post anterior vimos como crear un Motion Path desde Blend, y en este vamos a hacer lo mismo pero desde Visual Studio 2008, a base de código C#, como verdaderos programadores que somos. Comenzaremos creando un rectángulo idéntico al del ejemplo anterior.

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MotionPathVS.Window1"
x:Name="Window"
Title="Window1"
Width="640" Height="480">
<
Grid x:Name="LayoutRoot">
<
Rectangle HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="100"
Fill="#FFF50000" Stroke="#FF000000" x:Name="rect"/>
</
Grid>
</
Window>

Como vemos aquí, no necesitamos para nada el Path, que en nuestro primer ejemplo nos servía para establecer la ruta que seguiría el rectángulo. Y este será el único código XAML que veremos en este post, ya que toda la animación la construiremos, paso a paso, desde Visual Studio en C#. Así que empecemos. Lo primero que necesitamos es, valga la redundancia, crear la animación. Para ello crearemos un Storyboard al que añadiremos dos animaciones, una para desplazar el objeto por el eje X, otra para el eje Y.

Storyboard motion = new Storyboard();

DoubleAnimationUsingPath x = new DoubleAnimationUsingPath();
DoubleAnimationUsingPath y = new DoubleAnimationUsingPath();

motion.Children.Add(x);
motion.Children.Add(y);

Está animación tendrá que trabajar sobre la TranslateTransform del objeto que queremos desplazar, en este caso rect. Pero si nos fijamos en el código XAML, esa TranslateTransform no parece por ningún sitio, así que tendremos que crearla, asignársela a rect como RenderTransform y registrarla para que pueda ser utilizada por nuestra animación.

TranslateTransform translate = new TranslateTransform(0,200);
this.RegisterName("Translate", translate);
rect.RenderTransform = translate;

El próximo paso es construir el path que queremos que recorra nuestra animación. En este caso utilizaremos una Curva de Bézier, partiendo del punto (0, 200), finalizando en (500, 300) y con el punto de control en (150, 0). Esto generará de forma bastante sencilla una curva sobre la que desplazaremos el objeto entre los dos puntos.

PathGeometry geometry = new PathGeometry();
PathFigure figure = new PathFigure();
figure.StartPoint = new Point(0,200);
figure.Segments.Add(new QuadraticBezierSegment(new Point(150, 0), new Point(500, 300), false));
geometry.Figures.Add(figure);

Con esto tenemos los elementos básicos que necesitamos: la animación, la ruta y el objeto. Lo único que nos queda es relacionarlos entre sí. Utilizamos los métodos estáticos de la clase Storyboard para establecer en cada una de las animaciones el objeto y la propiedad del mismo con la que trabajaran. Con SetTargetName indicamos que ambas animaciones trabajaran sobre la transformación que registramos antes, y con SetTargetProperty hacemos que cada una de ellas trabaje con el eje correspondiente.

Storyboard.SetTargetName(x, "Translate");
Storyboard.SetTargetProperty(x, new PropertyPath(TranslateTransform.XProperty));
Storyboard.SetTargetName(y, "Translate");
Storyboard.SetTargetProperty(y, new PropertyPath(TranslateTransform.YProperty));

Después, añadimos a cada una de las animaciones el path que creamos anteriormente, y les indicamos que tendrán que utilizar como fuente el eje que les toque.

x.PathGeometry = geometry;
y.PathGeometry = geometry;

x.Source = PathAnimationSource.X;
y.Source = PathAnimationSource.Y;

Por último, añadimos una serie de atributos, más o menos esenciales, para dar forma a nuestra animación. Establecemos la duración de la misma en un segundo, hacemos que se repita indefinidamente para poder observar el efecto, y establecemos un ratio de deceleración de 0’3. Esto sirve para indicarle a la animación que el primer 70% del tiempo debe mantener una velocidad constante, y el 30% final debe decelerar, dándole un aspecto más real.

y.Duration = TimeSpan.FromMilliseconds(1000);
x.Duration = TimeSpan.FromMilliseconds(1000);

y.DecelerationRatio = 0.3;
x.DecelerationRatio = 0.3;

motion.RepeatBehavior = RepeatBehavior.Forever;

Con esto tenemos ya nuestra animación lista (podéis verla en el proyecto adjunto), y con el mismo método podemos crear todo tipo de animaciones para aplicar a nuestros objetos, sin necesidad de depender de Blend para nada.


Rock Tip. Ya que en el anterior hablábamos de Heavy Metal clásico, que mejor que traer hoy a los que son a juicio de muchos los más grandes del género, Manowar. Desde luego, tienen el honor de ser los que más ruido hacen encima de un escenario. De su último disco, Gods of War, llega este King of Kings para cerrar este post. Enjoy!

Publicado 1/4/2009 10:34 por Francisco Martinez | 2 comment(s)

Archivado en: