Compartir a través de


Tutorial: Crear un botón mediante XAML

El objetivo de este tutorial es aprender a crear un botón animado para usarlo en una aplicación de Windows Presentation Foundation (WPF). En este tutorial se usan estilos y una plantilla para crear un recurso de botón personalizado que permite reutilizar el código y la separación de la lógica de botón de la declaración de botón. Este tutorial se escribe completamente en lenguaje de marcado extensible de aplicaciones (XAML).

Importante

Este tutorial le guía por los pasos para crear la aplicación escribiendo o copiando y pegando lenguaje de marcado extensible de aplicaciones (XAML) en Visual Studio. Si prefiere aprender a usar un diseñador para crear la misma aplicación, consulte Crear un botón mediante Microsoft Expression Blend.

En la ilustración siguiente se muestran los botones terminados.

Botones personalizados creados mediante custom_button_AnimatedButton_5 XAML

Crear botones básicos

Comencemos creando un nuevo proyecto y agregando algunos botones a la ventana.

Para crear un nuevo proyecto de WPF y agregar botones a la ventana

  1. Inicie Visual Studio.

  2. Cree un nuevo proyecto de WPF: En el menú Archivo , seleccione Nuevoy, a continuación, haga clic en Proyecto. Busque la plantilla Aplicación de Windows (WPF) y asigne el nombre "AnimatedButton" al proyecto. Esto creará el esqueleto de la aplicación.

  3. Agregar botones predeterminados básicos: La plantilla proporciona todos los archivos que necesita para este tutorial. Abra el archivo Window1.xaml haciendo doble clic en él en el Explorador de soluciones. De forma predeterminada, hay un Grid elemento en Window1.xaml. Quite el Grid elemento y agregue algunos botones a la página Extensible Application Markup Language (XAML) escribiendo o copiando y pegando el código resaltado siguiente en Window1.xaml:

    <Window x:Class="AnimatedButton.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="AnimatedButton" Height="300" Width="300"
      Background="Black">
      <!-- Buttons arranged vertically inside a StackPanel. -->
      <StackPanel HorizontalAlignment="Left">
          <Button>Button 1</Button>
          <Button>Button 2</Button>
          <Button>Button 3</Button>
      </StackPanel>
    </Window>
    

    Presione F5 para ejecutar la aplicación; Debería ver un conjunto de botones que se parezcan a la ilustración siguiente.

    Tres botones básicos

    Ahora que ha creado los botones básicos, ha terminado de trabajar en el archivo Window1.xaml. El resto del tutorial se centra en el archivo app.xaml, definiendo estilos y una plantilla para los botones.

Establecer propiedades básicas

A continuación, vamos a establecer algunas propiedades en estos botones para controlar la apariencia y el diseño del botón. En lugar de establecer propiedades en los botones individualmente, usará recursos para definir propiedades de botón para toda la aplicación. Los recursos de aplicación son conceptualmente similares a las hojas de estilos en cascada externas (CSS) para las páginas web; Sin embargo, los recursos son mucho más eficaces que las hojas de estilos en cascada (CSS), como verá al final de este tutorial. Para obtener más información sobre los recursos, consulta Recursos XAML.

Para usar estilos para establecer propiedades básicas en los botones

  1. Defina un bloque Application.Resources: Abra app.xaml y agregue la marca resaltada siguiente si aún no está presente.

    <Application x:Class="AnimatedButton.App"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      StartupUri="Window1.xaml"
      >
      <Application.Resources>
        <!-- Resources for the entire application can be defined here. -->
      </Application.Resources>
    </Application>
    

    El ámbito del recurso viene determinado por dónde se define el recurso. La definición de recursos en Application.Resources el archivo app.xaml permite usar el recurso desde cualquier lugar de la aplicación. Para obtener más información sobre cómo definir el ámbito de los recursos, consulta Recursos XAML.

  2. Cree un estilo y defina los valores de propiedad básicos con él: Agregue el marcado siguiente al Application.Resources bloque . Este marcado crea un Style que se aplica a todos los botones de la aplicación, estableciendo los Width botones en 90 y en Margin 10:

    <Application.Resources>
      <Style TargetType="Button">
        <Setter Property="Width" Value="90" />
        <Setter Property="Margin" Value="10" />
      </Style>
    </Application.Resources>
    

    La TargetType propiedad especifica que el estilo se aplica a todos los objetos de tipo Button. Cada Setter establece un valor de propiedad diferente para .Style Por lo tanto, en este momento cada botón de la aplicación tiene un ancho de 90 y un margen de 10. Si presiona F5 para ejecutar la aplicación, verá la ventana siguiente.

    Botones con un ancho de 90 y un margen de 10

    Hay mucho más que puede hacer con estilos, incluidas una variedad de formas de ajustar los objetos de destino, especificar valores de propiedad complejos e incluso usar estilos como entrada para otros estilos. Para obtener más información, vea Aplicar estilos y plantillas.

  3. Establezca un valor de propiedad de estilo en un recurso: Los recursos permiten una manera sencilla de reutilizar los objetos y valores definidos habitualmente. Es especialmente útil definir valores complejos mediante recursos para que el código sea más modular. Agregue el código etiquetado resaltado siguiente a app.xaml.

    <Application.Resources>
      <LinearGradientBrush x:Key="GrayBlueGradientBrush" StartPoint="0,0" EndPoint="1,1">
        <GradientStop Color="DarkGray" Offset="0" />
        <GradientStop Color="#CCCCFF" Offset="0.5" />
        <GradientStop Color="DarkGray" Offset="1" />
      </LinearGradientBrush>
      <Style TargetType="{x:Type Button}">
        <Setter Property="Background" Value="{StaticResource GrayBlueGradientBrush}" />
        <Setter Property="Width" Value="80" />
        <Setter Property="Margin" Value="10" />
      </Style>
    </Application.Resources>
    

    Directamente debajo del bloque Application.Resources, ha creado un recurso denominado "GrayBlueGradientBrush". Este recurso define un degradado horizontal. Este recurso se puede usar como valor de propiedad desde cualquier lugar de la aplicación, incluido dentro del establecedor de estilo de botón para la Background propiedad . Ahora, todos los botones tienen un Background valor de propiedad de este degradado.

    Presione F5 para ejecutar la aplicación. Debería tener este aspecto.

    Botones con un fondo degradado

Crear una plantilla que defina el aspecto del botón

En esta sección, creará una plantilla que personalice la apariencia (presentación) del botón. La presentación del botón se compone de varios objetos, incluidos rectángulos y otros componentes para dar al botón un aspecto único.

Hasta ahora, el control de cómo se ven los botones en la aplicación se ha limitado a cambiar las propiedades del botón. ¿Qué ocurre si desea realizar cambios más radicales en la apariencia del botón? Las plantillas permiten un control eficaz sobre la presentación de un objeto. Dado que las plantillas se pueden usar dentro de estilos, puede aplicar una plantilla a todos los objetos a los que se aplica el estilo (en este tutorial, el botón).

Para usar la plantilla para definir el aspecto del botón

  1. Configure la plantilla: Dado que los controles como Button tienen una Template propiedad, puede definir el valor de la propiedad de plantilla igual que los demás valores de propiedad que hemos establecido en un Style mediante .Setter Agregue el marcado resaltado siguiente al estilo del botón.

    <Application.Resources>
      <LinearGradientBrush x:Key="GrayBlueGradientBrush"
        StartPoint="0,0" EndPoint="1,1">
        <GradientStop Color="DarkGray" Offset="0" />
        <GradientStop Color="#CCCCFF" Offset="0.5" />
        <GradientStop Color="DarkGray" Offset="1" />
      </LinearGradientBrush>
      <Style TargetType="{x:Type Button}">
        <Setter Property="Background" Value="{StaticResource GrayBlueGradientBrush}" />
        <Setter Property="Width" Value="80" />
        <Setter Property="Margin" Value="10" />
        <Setter Property="Template">
          <Setter.Value>
            <!-- The button template is defined here. -->
          </Setter.Value>
        </Setter>
      </Style>
    </Application.Resources>
    
  2. Modificar presentación del botón: En este momento, debe definir la plantilla. Agregue el marcado resaltado siguiente. Este marcado especifica dos Rectangle elementos con bordes redondeados, seguidos de .DockPanel DockPanel se utiliza para alojar el ContentPresenter del botón. Muestra ContentPresenter el contenido del botón. En este tutorial, el contenido es texto ("Botón 1", "Botón 2", "Botón 3"). Todos los componentes de plantilla (los rectángulos y DockPanel) se colocan dentro de un Grid.

    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" ClipToBounds="True">
          <!-- Outer Rectangle with rounded corners. -->
          <Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}" RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />
          <!-- Inner Rectangle with rounded corners. -->
          <Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stroke="Transparent" StrokeThickness="20" Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20" />
          <!-- Present Content (text) of the button. -->
          <DockPanel Name="myContentPresenterDockPanel">
            <ContentPresenter x:Name="myContentPresenter" Margin="20" Content="{TemplateBinding  Content}" TextBlock.Foreground="Black" />
          </DockPanel>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
    

    Presione F5 para ejecutar la aplicación. Debería tener este aspecto.

    Ventana con 3 botones

  3. Agregue un efecto de vidrio a la plantilla: A continuación, añadirá el efecto de vidrio. En primer lugar, cree algunos recursos que creen un efecto de degradado de vidrio. Agregue estos recursos de gradiente en cualquier parte del bloque Application.Resources.

    <Application.Resources>
      <GradientStopCollection x:Key="MyGlassGradientStopsResource">
        <GradientStop Color="WhiteSmoke" Offset="0.2" />
        <GradientStop Color="Transparent" Offset="0.4" />
        <GradientStop Color="WhiteSmoke" Offset="0.5" />
        <GradientStop Color="Transparent" Offset="0.75" />
        <GradientStop Color="WhiteSmoke" Offset="0.9" />
        <GradientStop Color="Transparent" Offset="1" />
      </GradientStopCollection>
      <LinearGradientBrush x:Key="MyGlassBrushResource"
        StartPoint="0,0" EndPoint="1,1" Opacity="0.75"
        GradientStops="{StaticResource MyGlassGradientStopsResource}" />
    <!-- Styles and other resources below here. -->
    

    Estos recursos se usan como el Fill de un rectángulo que insertamos en la Grid de la plantilla del botón. Agregue el marcado resaltado siguiente a la plantilla.

    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"
          ClipToBounds="True">
    
        <!-- Outer Rectangle with rounded corners. -->
        <Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"
          RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />
    
        <!-- Inner Rectangle with rounded corners. -->
        <Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch" Stroke="Transparent" StrokeThickness="20"
          Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20" />
    
        <!-- Glass Rectangle -->
        <Rectangle x:Name="glassCube" HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch"
          StrokeThickness="2" RadiusX="10" RadiusY="10" Opacity="0"
          Fill="{StaticResource MyGlassBrushResource}"
          RenderTransformOrigin="0.5,0.5">
          <Rectangle.Stroke>
            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
              <LinearGradientBrush.GradientStops>
                <GradientStop Offset="0.0" Color="LightBlue" />
                <GradientStop Offset="1.0" Color="Gray" />
              </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>
          </Rectangle.Stroke>
          <!-- These transforms have no effect as they are declared here.
          The reason the transforms are included is to be targets
          for animation (see later). -->
          <Rectangle.RenderTransform>
            <TransformGroup>
              <ScaleTransform />
              <RotateTransform />
            </TransformGroup>
          </Rectangle.RenderTransform>
          <!-- A BevelBitmapEffect is applied to give the button a "Beveled" look. -->
          <Rectangle.BitmapEffect>
            <BevelBitmapEffect />
          </Rectangle.BitmapEffect>
        </Rectangle>
    
        <!-- Present Text of the button. -->
        <DockPanel Name="myContentPresenterDockPanel">
          <ContentPresenter x:Name="myContentPresenter" Margin="20"
            Content="{TemplateBinding  Content}" TextBlock.Foreground="Black" />
        </DockPanel>
      </Grid>
    </ControlTemplate>
    </Setter.Value>
    

    Observe que el Opacity del rectángulo con la x:Name propiedad "glassCube" es 0, por lo que al ejecutar la muestra, no verá el rectángulo de vidrio superpuesto en la parte superior. Esto se debe a que más adelante agregaremos desencadenadores a la plantilla para cuando el usuario interactúe con el botón. Sin embargo, puede ver el aspecto del botón ahora cambiando el Opacity valor a 1 y ejecutando la aplicación. Consulte la ilustración siguiente. Antes de continuar con el paso siguiente, cambie el Opacity de vuelta a 0.

    Botones personalizados creados mediante custom_button_AnimatedButton_5 XAML

Crear interactividad de botón

En esta sección, creará desencadenadores de propiedades y desencadenadores de eventos para cambiar los valores de propiedad y ejecutar animaciones en respuesta a acciones del usuario, como mover el puntero del mouse sobre el botón y hacer clic.

Una manera fácil de agregar interactividad (mouse-over, mouse-leave, click, etc.) es definir desencadenadores dentro de la plantilla o estilo. Para crear un Trigger, defina una propiedad "condition" como: El valor de la propiedad del botón IsMouseOver es igual a true. A continuación, se definen configuradores (acciones) que tienen lugar cuando la condición del desencadenador es verdadera.

Para crear interactividad de botón

  1. Agregar desencadenadores de plantilla: Agregue el marcado resaltado a la plantilla.

    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Grid Width="{TemplateBinding Width}"
          Height="{TemplateBinding Height}" ClipToBounds="True">
    
          <!-- Outer Rectangle with rounded corners. -->
          <Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"
          RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent" />
    
          <!-- Inner Rectangle with rounded corners. -->
          <Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch" Stroke="Transparent"
            StrokeThickness="20"
            Fill="{TemplateBinding Background}" RadiusX="20" RadiusY="20"
          />
    
          <!-- Glass Rectangle -->
          <Rectangle x:Name="glassCube" HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch"
            StrokeThickness="2" RadiusX="10" RadiusY="10" Opacity="0"
            Fill="{StaticResource MyGlassBrushResource}"
            RenderTransformOrigin="0.5,0.5">
            <Rectangle.Stroke>
              <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                <LinearGradientBrush.GradientStops>
                  <GradientStop Offset="0.0" Color="LightBlue" />
                  <GradientStop Offset="1.0" Color="Gray" />
                </LinearGradientBrush.GradientStops>
              </LinearGradientBrush>
            </Rectangle.Stroke>
    
            <!-- These transforms have no effect as they
                 are declared here.
                 The reason the transforms are included is to be targets
                 for animation (see later). -->
            <Rectangle.RenderTransform>
              <TransformGroup>
                <ScaleTransform />
                <RotateTransform />
              </TransformGroup>
            </Rectangle.RenderTransform>
    
              <!-- A BevelBitmapEffect is applied to give the button a
                   "Beveled" look. -->
            <Rectangle.BitmapEffect>
              <BevelBitmapEffect />
            </Rectangle.BitmapEffect>
          </Rectangle>
    
          <!-- Present Text of the button. -->
          <DockPanel Name="myContentPresenterDockPanel">
            <ContentPresenter x:Name="myContentPresenter" Margin="20"
              Content="{TemplateBinding  Content}" TextBlock.Foreground="Black" />
          </DockPanel>
        </Grid>
    
        <ControlTemplate.Triggers>       <!-- Set action triggers for the buttons and define            what the button does in response to those triggers. -->     </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
    
  2. Agregar activadores de propiedad: Agregue el marcado resaltado al bloque ControlTemplate.Triggers

    <ControlTemplate.Triggers>
    
      <!-- Set properties when mouse pointer is over the button. -->   <Trigger Property="IsMouseOver" Value="True">     <!-- Below are three property settings that occur when the           condition is met (user mouses over button).  -->     <!-- Change the color of the outer rectangle when user           mouses over it. -->     <Setter Property ="Rectangle.Stroke" TargetName="outerRectangle"       Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />     <!-- Sets the glass opacity to 1, therefore, the           glass "appears" when user mouses over it. -->     <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />     <!-- Makes the text slightly blurry as though you           were looking at it through blurry glass. -->     <Setter Property="ContentPresenter.BitmapEffect"        TargetName="myContentPresenter">       <Setter.Value>         <BlurBitmapEffect Radius="1" />       </Setter.Value>     </Setter>   </Trigger>
    
    <ControlTemplate.Triggers/>
    

    Presione F5 para ejecutar la aplicación y ver el efecto mientras ejecuta el puntero del mouse sobre los botones.

  3. Agregue un desencadenador de foco: A continuación, agregaremos algunos establecedores similares para controlar el caso cuando el botón tenga el foco (por ejemplo, después de que el usuario lo haga clic).

    <ControlTemplate.Triggers>
    
      <!-- Set properties when mouse pointer is over the button. -->
      <Trigger Property="IsMouseOver" Value="True">
    
        <!-- Below are three property settings that occur when the
             condition is met (user mouses over button).  -->
        <!-- Change the color of the outer rectangle when user          mouses over it. -->
        <Setter Property ="Rectangle.Stroke" TargetName="outerRectangle"
          Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
    
        <!-- Sets the glass opacity to 1, therefore, the          glass "appears" when user mouses over it. -->
        <Setter Property="Rectangle.Opacity" Value="1"       TargetName="glassCube" />
    
        <!-- Makes the text slightly blurry as though you were          looking at it through blurry glass. -->
        <Setter Property="ContentPresenter.BitmapEffect"       TargetName="myContentPresenter">
          <Setter.Value>
            <BlurBitmapEffect Radius="1" />
          </Setter.Value>
        </Setter>
      </Trigger>
      <!-- Set properties when button has focus. -->   <Trigger Property="IsFocused" Value="true">     <Setter Property="Rectangle.Opacity" Value="1"       TargetName="glassCube" />     <Setter Property="Rectangle.Stroke" TargetName="outerRectangle"       Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />     <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube" />   </Trigger>
    
    </ControlTemplate.Triggers>
    

    Presione F5 para ejecutar la aplicación y haga clic en uno de los botones. Observe que el botón permanece resaltado después de hacer clic en él porque todavía tiene el foco. Si hace clic en otro botón, el nuevo botón obtiene el foco mientras el último lo pierde.

  4. Agregar animaciones paraMouseEnteryMouseLeave: A continuación, agregamos algunas animaciones a los desencadenadores. Agregue el siguiente marcado en cualquier lugar dentro del bloque ControlTemplate.Triggers.

    <!-- Animations that start when mouse enters and leaves button. -->
    <EventTrigger RoutedEvent="Mouse.MouseEnter">
      <EventTrigger.Actions>
        <BeginStoryboard Name="mouseEnterBeginStoryboard">
          <Storyboard>
          <!-- This animation makes the glass rectangle shrink in the X direction. -->
            <DoubleAnimation Storyboard.TargetName="glassCube"
              Storyboard.TargetProperty=
              "(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
              By="-0.1" Duration="0:0:0.5" />
            <!-- This animation makes the glass rectangle shrink in the Y direction. -->
            <DoubleAnimation
            Storyboard.TargetName="glassCube"
              Storyboard.TargetProperty=
              "(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
              By="-0.1" Duration="0:0:0.5" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger.Actions>
    </EventTrigger>
    <EventTrigger RoutedEvent="Mouse.MouseLeave">
      <EventTrigger.Actions>
        <!-- Stopping the storyboard sets all animated properties back to default. -->
        <StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard" />
      </EventTrigger.Actions>
    </EventTrigger>
    

    El rectángulo de vidrio se reduce cuando el puntero del mouse se mueve sobre el botón y vuelve al tamaño normal cuando el puntero sale.

    Existen dos animaciones que se activan cuando el puntero pasa por encima del botón (MouseEnter se genera el evento). Estas animaciones reducen el rectángulo de vidrio a lo largo del eje X e Y. Observe las propiedades de los DoubleAnimation elementos , Duration y By. Duration especifica que la animación se produce durante medio segundo y By especifica que el vidrio se reduce en 10%.

    El segundo desencadenador de eventos (MouseLeave) simplemente detiene el primero. Cuando se detiene Storyboard, todas las propiedades animadas vuelven a sus valores predeterminados. Por lo tanto, cuando el usuario mueve el puntero fuera del botón, el botón vuelve a la forma en que estaba antes de que el puntero del mouse se moviera sobre el botón. Para obtener más información sobre las animaciones, vea Información general sobre animaciones.

  5. Agregue una animación para cuando se haga clic en el botón: El último paso es agregar un desencadenador para cuando el usuario hace clic en el botón. Agregue el marcado siguiente en cualquier parte del ControlTemplate.Triggers bloque:

    <!-- Animation fires when button is clicked, causing glass to spin.  -->
    <EventTrigger RoutedEvent="Button.Click">
      <EventTrigger.Actions>
        <BeginStoryboard>
          <Storyboard>
            <DoubleAnimation Storyboard.TargetName="glassCube"
              Storyboard.TargetProperty=
              "(Rectangle.RenderTransform).(TransformGroup.Children)[1].(RotateTransform.Angle)"
              By="360" Duration="0:0:0.5" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger.Actions>
    </EventTrigger>
    

    Presione F5 para ejecutar la aplicación y haga clic en uno de los botones. Al hacer clic en un botón, el rectángulo de vidrio gira alrededor.

Resumen

En este tutorial, ha realizado los siguientes ejercicios:

  • Se dirigió Style a un tipo de objeto (Button).

  • Controladas las propiedades básicas de los botones en toda la aplicación usando Style.

  • Se crearon recursos como degradados que se usarán para los valores de propiedad de los Style establecedores.

  • Personaliza el aspecto de los botones de toda la aplicación aplicando una plantilla a los botones.

  • Comportamiento personalizado para los botones en respuesta a las acciones del usuario (como MouseEnter, MouseLeavey Click) que incluían efectos de animación.

Consulte también