Archives

Categories


Links




Locations of visitors to this page


El maravilloso universo de la ingenería y desarrollo de software


Como generar un botón reutilizable con Microsoft Expresion Blend 2 para Silverlight 2

Jun-132008

Una de las facilidades que ofrece Microsoft Expression Blend es la capacidad de integrar elementos de diseño fácilmente y de la mano con Visual Studio 2008 extender la funcionalidad de los elementos gráficos.

Veremos cómo podemos diseñar un control y agregar propiedades que permitan a nuestro control modificar su diseño en base a propiedades comunes.

El día de hoy generaremos un botón.

Inicializamos un nuevo proyecto con Microsoft Expression Blend de tipo Silverlight 2 Application

clip_image002

Una vez generada la solución agregamos un UserControl el cual llamaremos CustomButton

clip_image004

En nuestro CustomControl agregamos el siguiente código Xaml para darle un estilo a nuestro botón.

 

<UserControl xmlns="http://schemas.microsoft.com/client/2007" 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" x:Class="SampleApp.CustomButton" Width="Auto" Height="Auto"> <Grid Height="Auto" Width="Auto" x:Name="canvas" RenderTransformOrigin="0.5,0.5"> <Grid.RenderTransform> <TransformGroup> <ScaleTransform/> <SkewTransform/> <RotateTransform/> <TranslateTransform/> </TransformGroup> </Grid.RenderTransform> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.346*"/> <ColumnDefinition Width="0.256*"/> <ColumnDefinition Width="0.398*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="0.287*"/> <RowDefinition Height="0.235*"/> <RowDefinition Height="0.309*"/> <RowDefinition Height="0.169*"/> </Grid.RowDefinitions> <Rectangle Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"

Width="Auto" Fill="#FF0D3A66" Stroke="#FF000000" RadiusX="8" RadiusY="8" d:LayoutOverrides="HorizontalAlignment" Grid.RowSpan="4" Grid.ColumnSpan="3" x:Name="border"/> <Path Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"

Data="M71.25,29.125 C73.858894,29.351784 2.729677,28.617605 0,29.125 C0,13.039706 15.949856,0 35.625,0 C55.300144,0 71.25,13.039706 71.25,29.125 z"

Stretch="Fill" Grid.RowSpan="1" Grid.Row="3" Grid.ColumnSpan="1" d:LayoutOverrides="HorizontalAlignment" Grid.Column="1" Margin="0,0,0,1" x:Name="borderdown" RenderTransformOrigin="0.5,0.5"> <Path.RenderTransform> <TransformGroup> <ScaleTransform/> <SkewTransform/> <RotateTransform/> <TranslateTransform/> </TransformGroup> </Path.RenderTransform> <Path.Fill> <RadialGradientBrush GradientOrigin="0.495999991893768,-0.184000000357628"> <RadialGradientBrush.RelativeTransform> <TransformGroup> <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="-1.041" ScaleY="-1.989"/> <SkewTransform CenterX="0.5" CenterY="0.5"/> <RotateTransform CenterX="0.5" CenterY="0.5"/> <TranslateTransform Y="0.474"/> </TransformGroup> </RadialGradientBrush.RelativeTransform> <GradientStop Color="#FF0D3A66" Offset="1"/> <GradientStop Color="#7FFFFFFF" Offset="0"/> </RadialGradientBrush> </Path.Fill> </Path> <Path HorizontalAlignment="Stretch" VerticalAlignment="Stretch"

Data="M165.54631,113.71158 C165.54646,138.17401 129.82472,136.5 83.8125,136.5 C37.800278,136.5 2.568521,136.25545 2.1868401,113.71167 C2.2377911,113.72384 1.6872363,93.100006 2.1868401,93.110977 C13.487612,93.359039 140.10013,93.274727 165.27357,93.110977 C168.31805,93.091171 165.68532,113.73421 165.54631,113.71158 z"

Stretch="Fill" d:LayoutOverrides="HorizontalAlignment" Grid.RowSpan="2" Grid.ColumnSpan="3" Margin="2,5,2,0" x:Name="borderup"> <Path.Fill> <LinearGradientBrush EndPoint="0.51800000667572,0.994000017642975" StartPoint="0.512000024318695,-0.0670000016689301"> <GradientStop Color="#FF0D3A66" Offset="0.009"/> <GradientStop Color="#4CFFFFFF" Offset="1"/> </LinearGradientBrush> </Path.Fill> </Path> <TextBlock x:Name="text" Grid.ColumnSpan="3" Grid.Row="1" FontSize="14" Text="Texto" TextWrapping="Wrap"

Foreground="#FFFFFFFF" FontWeight="Bold" HorizontalAlignment="Center" d:LayoutOverrides="GridBox" Grid.Column="0" Grid.RowSpan="2"/> </Grid> </UserControl>

 

Nuestro botón quedaria de la siguiente manera:

image

Enseguida agregamos el código que permitira que nuestro control muestre las propiedades que nosotros deseamos extender.

A nuestro control agregaremos un estilo de letra y color de fondo por default.

public CustomButton()
        {
            InitializeComponent();
            FontSize = 14;
            ColorButton = Color.FromArgb(255, 13, 58, 102);
        }

Si deseamos que el usuario personalice por ejemplo el tamaño de la fuente del texto es necesario exponer una propiedad que permita manipular el tamaño de la fuente.

Veamos como generamos una propiedad para manipular el tamaño de la fuente de nuestro control.

Para este escenario es necesario agregar una propiedad pública, pero esta propiedad no es de un tipo especial llamado DependencyProperty el cual permite mantener el valor de una propiedad aún y cuando se serialice el objeto y además es si queremos que la propiedad sea visible en el Expression Blend, es necesario su utilización.

        // Using a DependencyProperty as the backing store for FontSize.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty FontSizeProperty =
            DependencyProperty.Register("FontSize", typeof(double), typeof(CustomButton), new PropertyMetadata(FontSizeChangedCallback));

Agregamos un propiedad tradicional pero con la diferencia que el valor es asignado a la propiedad de dependencia que acabamos de crear.

        public double FontSize
        {
            get { return (double)GetValue(FontSizeProperty); }
            set { SetValue(FontSizeProperty, value); }
        }

Finalmente agregamos un evento para que en el momento que el valor de nuestra propiedad cambie, asignemos el valor a nuestro control de texto, este texto debido a que se encuentra en el contexto de nuestro control es privado y no puede ser accedido si lo incluimos en otro control, página o contenedor.

        private static void FontSizeChangedCallback(DependencyObject obj,
                        DependencyPropertyChangedEventArgs args)
        {
            //Asigna el texto
            CustomButton button = obj as CustomButton;
            if (button != null)
            {
                button.text.FontSize = (double)args.NewValue;
            }
        }

Esta propiedad será visible en el diseñador de Expression.

Para incluir el control dentro de otra página o control de expression, simplemente es necesario buscarlo en la sección de Asset Library, en la sección  de Custom Controls, ahí ya aparecerá nuestra clase de CustomButton.

image

Arrastramos nuestro control y podremos ver el mismo diseño pero sin la posibilidad de modificar su estilo, pero si podremos modificar la nueva propiedad que acabamos de generar.

Nota: para que cualquier cambio hecho a nuestro control se vea reflejado, es necesario compilar la solución.

image

 

Podemos agregar más propiedades tales como configurar el color de fondo y el texto a mostrar.

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(CustomButton), new PropertyMetadata(TextChangedCallback));

        private static void TextChangedCallback(DependencyObject obj,
                        DependencyPropertyChangedEventArgs args)
        {
            //Asigna el texto
            CustomButton button = obj as CustomButton;
            if (button != null)
            {
                button.text.Text = args.NewValue as string;
            }
        }



        public Color ColorButton
        {
            get { return (Color)GetValue(ColorButtonProperty); }
            set { SetValue(ColorButtonProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Color.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ColorButtonProperty =
            DependencyProperty.Register("ColorButton", typeof(Color), typeof(CustomButton), new PropertyMetadata(ColorButtonChangedCallback));

        private static void ColorButtonChangedCallback(DependencyObject obj,
                        DependencyPropertyChangedEventArgs args)
        {
            //Asigna el texto
            CustomButton button = obj as CustomButton;
            if (button != null)
            {
                if (button.border.Fill is SolidColorBrush)
                {
                    SolidColorBrush solid = button.border.Fill as SolidColorBrush;
                    solid.Color = button.ColorButton;
                }
                if (button.borderdown.Fill is RadialGradientBrush)
                {
                    RadialGradientBrush radial = button.borderdown.Fill as RadialGradientBrush;
                    radial.GradientStops[0].Color = button.ColorButton;
                }
                if (button.borderup.Fill is LinearGradientBrush)
                {
                    LinearGradientBrush linear = button.borderup.Fill as LinearGradientBrush;
                    linear.GradientStops[0].Color = button.ColorButton;
                }
            }
        }

Con estas propiedades podemos personalizar nuestros botones.

 

image

Nos faltaría como agregar o extender eventos, pero ese tema lo tratare en otro post.

¿Y el código?

El código fuente de este control esta disponible aquí.

 
Posted by Efren Esteban Cruz Anguiano | 0 Comments | Bookmark with:        
Tags: Design, Silverlight

Links to this Post

Comments

Name:
URL:
Email:
Comments:

CAPTCHA Image Validation