Personalizar la apariencia de un control existente creando una clase ControlTemplateCustomizing the Appearance of an Existing Control by Creating a ControlTemplate

Un ControlTemplate especifica la estructura visual y el comportamiento visual de un control.A ControlTemplate specifies the visual structure and visual behavior of a control. Puede personalizar la apariencia de un control proporcionando una nueva ControlTemplate.You can customize the appearance of a control by giving it a new ControlTemplate. Cuando creas un ControlTemplate, reemplace la apariencia de un control existente sin cambiar su funcionalidad.When you create a ControlTemplate, you replace the appearance of an existing control without changing its functionality. Por ejemplo, puede que los botones de la aplicación redondos en lugar de la forma cuadrada predeterminada, pero el botón seguirá generando el Click eventos.For example, you can make the buttons in your application round instead of the default square shape, but the button will still raise the Click event.

En este tema se explica las distintas partes de un ControlTemplate, se muestra cómo crear una sencilla ControlTemplate para un Buttony se explica cómo entender el contrato de un control para que pueda personalizar su apariencia.This topic explains the various parts of a ControlTemplate, demonstrates creating a simple ControlTemplate for a Button, and explains how to understand the control contract of a control so that you can customize its appearance. Dado que se crea un ControlTemplate en XAMLXAML, puede cambiar el aspecto de un control sin escribir ningún código.Because you create a ControlTemplate in XAMLXAML, you can change a control's appearance without writing any code. También puede usar un diseñador, como Microsoft Expression Blend, para crear plantillas de control personalizado.You can also use a designer, such as Microsoft Expression Blend, to create custom control templates. En este tema se muestra ejemplos en los XAMLXAML que personalizar la apariencia de un Button y muestra el ejemplo completo al final del tema.This topic shows examples in the XAMLXAML that customize the appearance of a Button and lists the complete example at the end of the topic. Para más información acerca del uso de Expression Blend, consulte Aplicar estilos a un control que admite plantillas.For more information about using Expression Blend, see Styling a control that supports templates.

Las siguientes ilustraciones muestran un Button que usa el ControlTemplate que se crea en este tema.The following illustrations show a Button that uses the ControlTemplate that is created in this topic.

Botón con una plantilla de control personalizado. A button with a custom control template.
Un botón que usa una plantilla de control personalizado.A button that uses a custom control template

Botón con un borde rojo. A button with a red border.
Un botón que usa una plantilla de control personalizado y tiene el puntero del mouse sobre él.A button that uses a custom control template and has the mouse pointer over it

Requisitos previosPrerequisites

En este tema se supone que sabe cómo crear y usar controles y estilos, como se describe en Controls (Controles).This topic assumes that you understand how to create and use controls and styles as discussed in Controls. Los conceptos tratados en este tema se aplican a los elementos que heredan de la Control (clase), excepto para el UserControl.The concepts discussed in this topic apply to elements that inherit from the Control class, except for the UserControl. No se puede aplicar un ControlTemplate a un UserControl.You cannot apply a ControlTemplate to a UserControl.

Cuándo se debe crear un control ControlTemplateWhen You Should Create a ControlTemplate

Los controles tienen muchas propiedades, como Background, Foreground, y FontFamily, que puede establecer para especificar distintos aspectos de la apariencia del control, pero los cambios que puede hacer al establecer estas propiedades son limitados.Controls have many properties, such as Background, Foreground, and FontFamily, that you can set to specify different aspects of the control's appearance, but the changes that you can make by setting these properties are limited. Por ejemplo, puede establecer el Foreground propiedad a azul y FontStyle en cursiva en un CheckBox.For example, you can set the Foreground property to blue and FontStyle to italic on a CheckBox.

Sin la capacidad para crear un nuevo ControlTemplate para los controles, todos los controles de cada WPFWPF-aplicación basada en tendría el mismo aspecto general, lo que limitaría la capacidad de crear una aplicación con una apariencia personalizada.Without the ability to create a new ControlTemplate for controls, all controls in every WPFWPF-based application would have the same general appearance, which would limit the ability to create an application with a custom look and feel. De forma predeterminada, cada CheckBox tiene características similares.By default, every CheckBox has similar characteristics. Por ejemplo, el contenido de la CheckBox siempre está a la derecha del indicador de selección, y siempre se utiliza la marca de verificación para indicar que el CheckBox está seleccionada.For example, the content of the CheckBox is always to the right of the selection indicator, and the check mark is always used to indicate that the CheckBox is selected.

Crear un ControlTemplate cuando desee personalizar la apariencia del control más allá de hará lo hace la configuración de las demás propiedades en el control.You create a ControlTemplate when you want to customize the control's appearance beyond what setting the other properties on the control will do. En el ejemplo de la CheckBox, suponga que desea que el contenido de la casilla de verificación por encima del indicador de selección y desea que una X para indicar que el CheckBox está seleccionada.In the example of the CheckBox, suppose that you want the content of the check box to be above the selection indicator and you want an X to indicate that the CheckBox is selected. Especifique estos cambios en el ControlTemplate de la CheckBox.You specify these changes in the ControlTemplate of the CheckBox.

La siguiente ilustración muestra un CheckBox que usa un valor predeterminado ControlTemplate.The following illustration shows a CheckBox that uses a default ControlTemplate.

Casilla con la plantilla de control predeterminada. A checkbox with the default control template.
Un control CheckBox que usa la plantilla de control predeterminadaA CheckBox that uses the default control template

La siguiente ilustración muestra un CheckBox que usa un ControlTemplate para colocar el contenido de la CheckBox anteriormente el indicador de selección y muestra una X cuando el CheckBox está seleccionada.The following illustration shows a CheckBox that uses a custom ControlTemplate to place the content of the CheckBox above the selection indicator and displays an X when the CheckBox is selected.

Casilla con una plantilla de control personalizado. A checkbox with a custom control template.
Un control CheckBox que usa una plantilla de control personalizadoA CheckBox that uses a custom control template

El ControlTemplate para el CheckBox en este ejemplo es relativamente compleja, por lo que en este tema se usa un ejemplo más sencillo de creación de un ControlTemplate para un Button.The ControlTemplate for the CheckBox in this sample is relatively complex, so this topic uses a simpler example of creating a ControlTemplate for a Button.

Cambio de la estructura visual de un controlChanging the Visual Structure of a Control

En WPFWPF, un control a menudo es una composición FrameworkElement objetos.In WPFWPF, a control is often a composite FrameworkElement objects. Cuando creas un ControlTemplate, combina FrameworkElement objetos que se va a crear un control único.When you create a ControlTemplate, you combine FrameworkElement objects to build a single control. Un ControlTemplate debe tener una única FrameworkElement como su elemento raíz.A ControlTemplate must have only one FrameworkElement as its root element. El elemento raíz normalmente contiene otros FrameworkElement objetos.The root element usually contains other FrameworkElement objects. La combinación de objetos constituye la estructura visual del control.The combination of objects makes up the control's visual structure.

En el ejemplo siguiente se crea un personalizado ControlTemplate para el Button.The following example creates a custom ControlTemplate for the Button. El ControlTemplate crea la estructura visual de la Button.The ControlTemplate creates the visual structure of the Button. En este ejemplo no cambia la apariencia del botón al mover el puntero del mouse sobre él o hacer clic en él.This example does not change the button's appearance when you move the mouse pointer over it or click it. El cambio de la apariencia del botón cuando se encuentra en un estado diferente se explica más adelante en este tema.Changing the button's appearance when it is in a different state is discussed later in this topic.

En este ejemplo, la estructura visual consta de las siguientes partes:In this example, the visual structure consists of the following parts:

<ControlTemplate TargetType="Button">
  <Border Name="RootElement">

    <!--Create the SolidColorBrush for the Background 
        as an object elemment and give it a name so 
        it can be referred to elsewhere in the
        control template.-->
    <Border.Background>
      <SolidColorBrush x:Name="BorderBrush" Color="Black"/>
    </Border.Background>

    <!--Create a border that has a different color
        by adding smaller grid. The background of 
        this grid is specificied by the button's 
        Background property.-->
    <Grid Margin="4" Background="{TemplateBinding Background}">

      <!--Use a ContentPresenter to display the Content of
          the Button.-->
      <ContentPresenter
        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
        Margin="4,5,4,4" />
    </Grid>

  </Border>
</ControlTemplate>

Conservación de la funcionalidad de las propiedades de un control mediante TemplateBindingPreserving the Functionality of a Control's Properties by Using TemplateBinding

Cuando se crea un nuevo ControlTemplate, todavía puede usar las propiedades públicas para cambiar la apariencia del control.When you create a new ControlTemplate, you still might want to use the public properties to change the control's appearance. El TemplateBinding extensión de marcado enlaza una propiedad de un elemento que se encuentra en la ControlTemplate a una propiedad pública que está definida por el control.The TemplateBinding markup extension binds a property of an element that is in the ControlTemplate to a public property that is defined by the control. Cuando se usa TemplateBinding, se habilitan propiedades en el control que actúan como parámetros de la plantilla.When you use TemplateBinding, you enable properties on the control to act as parameters to the template. Es decir, cuando se establece una propiedad de un control, ese valor se pasa al elemento que tiene la extensión TemplateBinding.That is, when a property on a control is set, that value is passed on to the element that has the TemplateBinding on it.

En el ejemplo siguiente se repite la parte del ejemplo anterior que usa el TemplateBinding extensión de marcado para enlazar propiedades de elementos que se encuentran en el ControlTemplate a las propiedades públicas definidas por el botón.The following example repeats the part of the preceding example that uses the TemplateBinding markup extension to bind properties of elements that are in the ControlTemplate to public properties that are defined by the button.

<Grid Margin="4" Background="{TemplateBinding Background}">

  <!--Use a ContentPresenter to display the Content of
      the Button.-->
  <ContentPresenter
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    Margin="4,5,4,4" />
</Grid>

En este ejemplo, el Grid tiene su Panel.Background plantilla de la propiedad enlazada a Control.Background.In this example, the Grid has its Panel.Background property template bound to Control.Background. Porque Panel.Background está enlazado a plantilla, puede crear varios botones que usan los mismos ControlTemplate y establezca el Control.Background en valores distintos en cada botón.Because Panel.Background is template bound, you can create multiple buttons that use the same ControlTemplate and set the Control.Background to different values on each button. Si Control.Background plantilla no se enlazó a una propiedad de un elemento en el ControlTemplate, estableciendo el Control.Background de un botón no tendría ningún impacto en la apariencia del botón.If Control.Background was not template bound to a property of an element in the ControlTemplate, setting the Control.Background of a button would have no impact on the button's appearance.

Tenga en cuenta que los nombres de las dos propiedades no tienen que ser idénticos.Note that the names of the two properties do not need to be identical. En el ejemplo anterior, el Control.HorizontalContentAlignment propiedad de la Button plantilla depende de la FrameworkElement.HorizontalAlignment propiedad de la ContentPresenter.In the preceding example, the Control.HorizontalContentAlignment property of the Button is template bound to the FrameworkElement.HorizontalAlignment property of the ContentPresenter. Esto permite que el contenido del botón se sitúe horizontalmente.This enables the content of the button to be positioned horizontally. ContentPresenter no tiene una propiedad denominada HorizontalContentAlignment, pero Control.HorizontalContentAlignment pueden estar limitados por FrameworkElement.HorizontalAlignment.ContentPresenter does not have a property named HorizontalContentAlignment, but Control.HorizontalContentAlignment can be bound to FrameworkElement.HorizontalAlignment. Cuando la plantilla enlaza una propiedad, asegúrese de que las propiedades de origen y de destino sean del mismo tipo.When you template bind a property, be sure that the target and source properties are the same type.

La Control clase define varias propiedades que deben usarse para tener un efecto en el control cuando se configuran mediante la plantilla de control.The Control class defines several properties that must be used by the control template to have an effect on the control when they are set. El modo ControlTemplate usa la propiedad depende de la propiedad.How the ControlTemplate uses the property depends on the property. El ControlTemplate debe usar la propiedad en una de las maneras siguientes:The ControlTemplate must use the property in one of the following ways:

En la tabla siguiente se enumera las propiedades visuales heredadas por un control desde el Control clase.The following table lists the visual properties inherited by a control from the Control class. También se indica si la plantilla de control predeterminado de un control usa el valor de propiedad heredado o si debe estar enlazado a plantilla.It also indicates whether the default control template of a control uses the inherited property value or if it must be template bound.

PropiedadProperty Método de usoUsage method
Background Enlace a plantillaTemplate binding
BorderThickness Enlace a plantillaTemplate binding
BorderBrush Enlace a plantillaTemplate binding
FontFamily Herencia de propiedad o enlace a plantillaProperty inheritance or template binding
FontSize Herencia de propiedad o enlace a plantillaProperty inheritance or template binding
FontStretch Herencia de propiedad o enlace a plantillaProperty inheritance or template binding
FontWeight Herencia de propiedad o enlace a plantillaProperty inheritance or template binding
Foreground Herencia de propiedad o enlace a plantillaProperty inheritance or template binding
HorizontalContentAlignment Enlace a plantillaTemplate binding
Padding Enlace a plantillaTemplate binding
VerticalContentAlignment Enlace a plantillaTemplate binding

La tabla enumeran las propiedades visuales heredadas de la Control clase.The table lists only the visual properties inherited from the Control class. Además de las propiedades enumeradas en la tabla, un control puede heredar también las DataContext, Language, y TextDecorations las propiedades del elemento de marco de trabajo primario.Apart from the properties listed in the table, a control may also inherit the DataContext, Language, and TextDecorations properties from the parent framework element.

Además, si la ContentPresenter está en el ControlTemplate de un ContentControl, el ContentPresenter se enlazará automáticamente a la ContentTemplate y Content propiedades.Also, if the ContentPresenter is in the ControlTemplate of a ContentControl, the ContentPresenter will automatically bind to the ContentTemplate and Content properties. Del mismo modo, un ItemsPresenter que se encuentra en la ControlTemplate de un ItemsControl se enlazará automáticamente a la Items y ItemsPresenter propiedades.Likewise, an ItemsPresenter that is in the ControlTemplate of an ItemsControl will automatically bind to the Items and ItemsPresenter properties.

El ejemplo siguiente crea dos botones que usan el ControlTemplate definido en el ejemplo anterior.The following example creates two buttons that use the ControlTemplate defined in the preceding example. El ejemplo se establece la Background, Foreground, y FontSize las propiedades de cada botón.The example sets the Background, Foreground, and FontSize properties on each button. Establecer el Background propiedad tiene un efecto porque está enlazada a plantilla en el ControlTemplate.Setting the Background property has an effect because it is template bound in the ControlTemplate. Aunque el Foreground y FontSize propiedades no están enlazado a plantilla, establecerlas tiene un efecto porque sus valores son heredados.Even though the Foreground and FontSize properties are not template bound, setting them has an effect because their values are inherited.

<StackPanel>
  <Button Style="{StaticResource newTemplate}" 
          Background="Navy" Foreground="White" FontSize="14"
          Content="Button1"/>

  <Button Style="{StaticResource newTemplate}" 
          Background="Purple" Foreground="White" FontSize="14"
          Content="Button2" HorizontalContentAlignment="Left"/>
</StackPanel>

El ejemplo anterior genera un resultado similar a la siguiente ilustración.The preceding example produces output that is similar to the following illustration.

Dos botones, uno azul y otro púrpura. Two buttons, one blue and one purple.
Dos botones con diferentes colores de fondoTwo buttons with different background colors

Cambio de la apariencia de un control según su estadoChanging the Appearance of a Control Depending on Its State

La diferencia entre un botón con su apariencia predeterminada y el botón del ejemplo anterior es que el botón predeterminado cambia sutilmente cuando se encuentra en estados diferentes.The difference between a button with its default appearance and the button in the preceding example is that the default button subtly changes when it is in different states. Por ejemplo, la apariencia del botón predeterminado cambia cuando se presiona el botón o cuando se sitúa el puntero del mouse sobre él.For example, the default button's appearance changes when the button is pressed, or when the mouse pointer is over the button. Aunque el ControlTemplate no cambia la funcionalidad de un control, cambia el comportamiento visual del control.Although the ControlTemplate does not change the functionality of a control, it does change the control's visual behavior. Un comportamiento visual describe la apariencia del control cuando se encuentra en un estado determinado.A visual behavior describes the control appearance when it is in a certain state. Para comprender la diferencia entre la funcionalidad y el comportamiento visual de un control, considere el ejemplo del botón.To understand the difference between the functionality and visual behavior of a control, consider the button example. La funcionalidad del botón consiste en generar el Click eventos cuando se hace clic en, pero el comportamiento visual del botón es cambiar su apariencia cuando está señalado o presiona.The button's functionality is to raise the Click event when it is clicked, but the button's visual behavior is to change its appearance when it is pointed to or pressed.

Usa VisualState objetos para especificar la apariencia de un control cuando se encuentra en un estado determinado.You use VisualState objects to specify the appearance of a control when it is in a certain state. Un VisualState contiene un Storyboard que cambia la apariencia de los elementos que se encuentran en el ControlTemplate.A VisualState contains a Storyboard that changes the appearance of the elements that are in the ControlTemplate. No tiene que escribir ningún código para que esto suceda, porque la lógica del control cambia de estado mediante el VisualStateManager.You do not have to write any code to make this occur because the control's logic changes state by using the VisualStateManager. Cuando el control entra en el estado especificado por el VisualState.Name propiedad, el Storyboard comienza.When the control enters the state that is specified by the VisualState.Name property, the Storyboard begins. Cuando el control sale del estado, el Storyboard se detiene.When the control exits the state, the Storyboard stops.

El ejemplo siguiente se muestra el VisualState que cambia la apariencia de un Button cuando el puntero del mouse está encima de él.The following example shows the VisualState that changes the appearance of a Button when the mouse pointer is over it. El Storyboard cambia el color del borde del botón cambiando el color de la BorderBrush.The Storyboard changes the button's border color by changing the color of the BorderBrush. Si hace referencia a la ControlTemplate ejemplo al principio de este tema, recordará que BorderBrush es el nombre de la SolidColorBrush que se asigna a la Background de la Border.If you refer to the ControlTemplate example at the beginning of this topic, you will recall that BorderBrush is the name of the SolidColorBrush that is assigned to the Background of the Border.

<!--Change the border of the button to red when the
    mouse is over the button.-->
<VisualState x:Name="MouseOver">
  <Storyboard>
    <ColorAnimation Storyboard.TargetName="BorderBrush"     
                    Storyboard.TargetProperty="Color"
                    To="Red" />

  </Storyboard>
</VisualState>

El control es responsable de definir los estados como parte de su contrato de control, que se describe de manera detallada en Personalización de otros controles mediante la comprensión del contrato de control más adelante en este tema.The control is responsible for defining the states as part of its control contract, which is discussed in detail in Customizing Other Controls by Understanding the Control Contract later in this topic. En la tabla siguiente se muestra los Estados que se especifican para el Button.The following table lists the states that are specified for the Button.

Nombre de VisualStateVisualState Name Nombre de VisualStateGroupVisualStateGroup Name DescripciónDescription
NormalNormal CommonStatesCommonStates El estado predeterminado.The default state.
MouseOverMouseOver CommonStatesCommonStates El puntero del mouse se coloca sobre el control.The mouse pointer is positioned over the control.
PresionadoPressed CommonStatesCommonStates El control está presionado.The control is pressed.
DeshabilitadoDisabled CommonStatesCommonStates El control está deshabilitado.The control is disabled.
Con focoFocused FocusStatesFocusStates El control tiene el foco.The control has focus.
Sin focoUnfocused FocusStatesFocusStates El control no tiene el foco.The control does not have focus.

El Button define dos grupos de estados: el CommonStates grupo contiene el Normal, MouseOver, Pressed, y Disabled Estados.The Button defines two state groups: the CommonStates group contains the Normal, MouseOver, Pressed, and Disabled states. El grupo FocusStates contiene los estados Focused y Unfocused.The FocusStates group contains the Focused and Unfocused states. Los estados en el mismo grupo de estado son mutuamente excluyentes.States in the same state group are mutually exclusive. El control siempre está exactamente en un estado por grupo.The control is always in exactly one state per group. Por ejemplo, un Button puede tener el foco cuando el puntero del mouse no está sobre él, por lo tanto un Button en el Focused estado puede estar en el MouseOver, Pressed, o Normal estado.For example, a Button can have focus even when the mouse pointer is not over it, so a Button in the Focused state can be in the MouseOver, Pressed, or Normal state.

Agregar VisualState objetos VisualStateGroup objetos.You add VisualState objects to VisualStateGroup objects. Agregar VisualStateGroup objetos a la VisualStateGroups propiedad adjunta.You add VisualStateGroup objects to the VisualStateGroups attached property. En el ejemplo siguiente se define la VisualState de objetos para el Normal, MouseOver, y Pressed Estados, que están en el CommonStates grupo.The following example defines the VisualState objects for the Normal, MouseOver, and Pressed states, which are all in the CommonStates group. El Name de cada VisualState coincide con el nombre de la tabla anterior.The Name of each VisualState matches the name in the preceding table. El estado Disabled y los estados del grupo FocusStates se omiten para abreviar el ejemplo, pero se incluyen en el ejemplo completo al final de este tema.The Disabled state and the states in the FocusStates group are omitted to keep the example short, but they are included in the entire example at the end of this topic.

Nota

Asegúrese de establecer el VisualStateGroups propiedad adjunta en la raíz FrameworkElement de la ControlTemplate.Be sure to set the VisualStateGroups attached property on the root FrameworkElement of the ControlTemplate.

<ControlTemplate TargetType="Button">
  <Border Name="RootElement">

    <VisualStateManager.VisualStateGroups>

      <!--Define the states and transitions for the common states.
          The states in the VisualStateGroup are mutually exclusive to
          each other.-->
      <VisualStateGroup x:Name="CommonStates">

        <!--The Normal state is the state the button is in
            when it is not in another state from this VisualStateGroup.-->
        <VisualState x:Name="Normal" />

        <!--Change the SolidColorBrush, BorderBrush, to red when the
            mouse is over the button.-->
        <VisualState x:Name="MouseOver">
          <Storyboard>
            <ColorAnimation Storyboard.TargetName="BorderBrush" 
                            Storyboard.TargetProperty="Color" 
                            To="Red" />
          </Storyboard>
        </VisualState>

        <!--Change the SolidColorBrush, BorderBrush, to Transparent when the
            button is pressed.-->
        <VisualState x:Name="Pressed">
          <Storyboard>
            <ColorAnimation Storyboard.TargetName="BorderBrush" 
                            Storyboard.TargetProperty="Color"
                            To="Transparent"/>
          </Storyboard>
        </VisualState>

        <!--The Disabled state is omitted for brevity.-->
      </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <Border.Background>
      <SolidColorBrush x:Name="BorderBrush" Color="Black"/>
    </Border.Background>

    <Grid Background="{TemplateBinding Background}" Margin="4">
      <ContentPresenter
        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
        Margin="4,5,4,4" />
    </Grid>
  </Border>
</ControlTemplate>

El ejemplo anterior genera un resultado similar a las siguientes ilustraciones.The preceding example produces output that is similar to the following illustrations.

Botón con una plantilla de control personalizado. A button with a custom control template.
Un botón que usa una plantilla de control personalizado en el estado normalA button that uses a custom control template in the normal state

Botón con un borde rojo. A button with a red border.
Un botón que usa una plantilla de control personalizado en el estado de pasar el mouseA button that uses a custom control template in the mouse over state

El borde es transparente en un botón presionado. The border is transparent on a pressed button.
Un botón que usa una plantilla de control personalizado en el estado presionadoA button that uses a custom control template in the pressed state

Para encontrar los estados visuales de los controles que se incluyen con WPFWPF, consulte Estilos y plantillas de controles.To find the visual states for controls that are included with WPFWPF, see Control Styles and Templates.

Especificación del comportamiento de un control cuando realiza la transición entre estadosSpecifying the Behavior of a Control When It Transitions Between States

En el ejemplo anterior, la apariencia del botón también cambia cuando el usuario hace clic en él, pero a menos que se presione el botón durante un segundo completo, el usuario no verá el efecto.In the preceding example, the appearance of the button also changes when the user clicks it, but unless the button is pressed for a full second, the user does not see the effect. De forma predeterminada, la animación tarda un segundo en producirse.By default, the animation takes one second to occur. Dado que es probable que los usuarios hacer clic y suelte un botón en mucho menos tiempo, los comentarios visuales no será efectivo si deja el ControlTemplate en su estado predeterminado.Because users are likely to click and release a button in much less time, the visual feedback will not be effective if you leave the ControlTemplate in its default state.

Puede especificar la cantidad de tiempo que tarda en producirse para una transición suave de un control de un estado a otro mediante la adición de una animación VisualTransition objetos a la ControlTemplate.You can specify the amount of time that it takes an animation to occur to smoothly transition a control from one state to another by adding VisualTransition objects to the ControlTemplate. Cuando creas un VisualTransition, especifique uno o varios de los siguientes:When you create a VisualTransition, you specify one or more of the following:

  • El tiempo que tarda en producirse una transición entre estados.The time it takes for a transition between states to occur.

  • Los cambios adicionales en la apariencia del control que se producen en el momento de la transición.Additional changes in the control's appearance that occur at the time of the transition.

  • Qué estados el VisualTransition se aplica a.Which states the VisualTransition is applied to.

Especificación de la duración de una transiciónSpecifying the Duration of a Transition

Puede especificar cuánto tiempo tarda una transición estableciendo el GeneratedDuration propiedad.You can specify how long a transition takes by setting the GeneratedDuration property. El ejemplo anterior tiene un VisualState que especifica que el borde del botón se vuelve transparente cuando se presiona el botón, pero la animación tarda demasiado tiempo en advertirse si el botón está presionado y soltado de rápidamente.The preceding example has a VisualState that specifies that the button's border becomes transparent when the button is pressed, but the animation takes too long to be noticeable if the button is quickly pressed and released. Puede usar un VisualTransition para especificar la cantidad de tiempo que tarda el control para realizar la transición al estado presionado.You can use a VisualTransition to specify the amount of time it takes the control to transition into the pressed state. En el ejemplo siguiente se especifica que el control tarda una centésima de segundo en pasar al estado presionado.The following example specifies that the control takes one hundredth of a second to go into the pressed state.

<!--Take one hundredth of a second to transition to the
    Pressed state.-->
<VisualTransition To="Pressed" 
                  GeneratedDuration="0:0:0.01" />

Especificación de cambios en la apariencia del control durante una transiciónSpecifying Changes to the Control's Appearance During a Transition

El VisualTransition contiene un Storyboard que comienza cuando el control realiza la transición entre Estados.The VisualTransition contains a Storyboard that begins when the control transitions between states. Por ejemplo, puede especificar que se produzca una determinada animación cuando el control pase del estado MouseOver al estado Normal.For example, you can specify that a certain animation occurs when the control transitions from the MouseOver state to the Normal State. En el ejemplo siguiente se crea un VisualTransition que especifica que, cuando el usuario mueve el puntero del mouse fuera del botón, el borde del botón cambia a azul, y, luego a amarillo, negro en 1,5 segundos.The following example creates a VisualTransition that specifies that when the user moves the mouse pointer away from the button, the button's border changes to blue, then to yellow, then to black in 1.5 seconds.

<!--Take one and a half seconds to transition from the
    MouseOver state to the Normal state. 
    Have the SolidColorBrush, BorderBrush, fade to blue, 
    then to yellow, and then to black in that time.-->
<VisualTransition From="MouseOver" To="Normal" 
                      GeneratedDuration="0:0:1.5">
  <Storyboard>
    <ColorAnimationUsingKeyFrames
      Storyboard.TargetProperty="Color"
      Storyboard.TargetName="BorderBrush"
      FillBehavior="HoldEnd" >

      <ColorAnimationUsingKeyFrames.KeyFrames>

        <LinearColorKeyFrame Value="Blue" 
          KeyTime="0:0:0.5" />
        <LinearColorKeyFrame Value="Yellow" 
          KeyTime="0:0:1" />
        <LinearColorKeyFrame Value="Black" 
          KeyTime="0:0:1.5" />

      </ColorAnimationUsingKeyFrames.KeyFrames>
    </ColorAnimationUsingKeyFrames>
  </Storyboard>
</VisualTransition>

Especificación de cuándo aplicar un objeto VisualTransitionSpecifying When a VisualTransition Is Applied

Un VisualTransition puede restringirse para aplicar solo a determinados Estados, o se puede aplicar cada vez que el control realiza la transición entre Estados.A VisualTransition can be restricted to apply to only certain states, or it can be applied any time the control transitions between states. En el ejemplo anterior, el VisualTransition se aplica cuando el control pasa de la MouseOver estado el Normal estado; en el ejemplo anterior, el VisualTransition se aplica cuando el control entra en el Pressed estado.In the preceding example, the VisualTransition is applied when the control goes from the MouseOver state to the Normal state; in the example before that, the VisualTransition is applied when the control goes into the Pressed state. Restringir cuándo un VisualTransition se aplica estableciendo el To y From propiedades.You restrict when a VisualTransition is applied by setting the To and From properties. En la tabla siguiente se describen los niveles de restricción del más al menos restrictivo.The following table describes the levels of restriction from most restrictive to least restrictive.

Tipo de restricciónType of restriction Valor de DesdeValue of From Valor de HastaValue of To
Desde un estado especificado hasta otro estado especificadoFrom a specified state to another specified state El nombre de un VisualStateThe name of a VisualState El nombre de un VisualStateThe name of a VisualState
Desde cualquier estado hasta un estado especificadoFrom any state to a specified state Sin establecerNot set El nombre de un VisualStateThe name of a VisualState
Desde un estado especificado hasta cualquier estadoFrom a specified state to any state El nombre de un VisualStateThe name of a VisualState Sin establecerNot set
Desde cualquier estado hasta cualquier otro estadoFrom any state to any other state Sin establecerNot set Sin establecerNot set

Puede tener varios VisualTransition objetos en un VisualStateGroup que hacen referencia al mismo estado, pero que se usarán en el orden que especifica la tabla anterior.You can have multiple VisualTransition objects in a VisualStateGroup that refer to the same state, but they will be used in the order that the previous table specifies. En el ejemplo siguiente, hay dos VisualTransition objetos.In the following example, there are two VisualTransition objects. Cuando el control realiza la transición desde el Pressed estado el MouseOver estado, el VisualTransition que tiene ambos From y To se usa el conjunto.When the control transitions from the Pressed state to the MouseOver state, the VisualTransition that has both From and To set is used. Cuando el control realiza la transición de un estado que no es Pressed al estado MouseOver, se usa el otro estado.When the control transitions from a state that is not Pressed to the MouseOver state, the other state is used.

<!--Take one half second to trasition to the MouseOver state.-->
<VisualTransition To="MouseOver" 
                  GeneratedDuration="0:0:0.5" />

<!--Take one hundredth of a second to transition from the
    Pressed state to the MouseOver state.-->
<VisualTransition From="Pressed" To="MouseOver" 
                  GeneratedDuration="0:0:0.01" />

El VisualStateGroup tiene un Transitions propiedad que contiene el VisualTransition objetos que se aplican a la VisualState objetos en el VisualStateGroup.The VisualStateGroup has a Transitions property that contains the VisualTransition objects that apply to the VisualState objects in the VisualStateGroup. Como el ControlTemplate autor, es gratuitas incluirlos VisualTransition que desee.As the ControlTemplate author, you are free to include any VisualTransition you want. Sin embargo, si la To y From propiedades se establecen en los nombres de estado que no están en el VisualStateGroup, el VisualTransition se omite.However, if the To and From properties are set to state names that are not in the VisualStateGroup, the VisualTransition is ignored.

El ejemplo siguiente se muestra el VisualStateGroup para el CommonStates.The following example shows the VisualStateGroup for the CommonStates. El ejemplo define un VisualTransition para cada uno de los siguientes del botón realiza la transición.The example defines a VisualTransition for each of the button's following transitions.

  • Al estado Pressed.To the Pressed state.

  • Al estado MouseOver.To the MouseOver state.

  • Desde el estado Pressed hasta el estado MouseOver.From the Pressed state to the MouseOver state.

  • Desde el estado MouseOver hasta el estado Normal.From the MouseOver state to the Normal state.

<VisualStateGroup x:Name="CommonStates">

  <!--Define the VisualTransitions that
      can be used when the control transitions 
      between VisualStates that are defined in the
      VisualStatGroup.-->
  <VisualStateGroup.Transitions>

    <!--Take one hundredth of a second to 
        transition to the Pressed state.-->
    <VisualTransition To="Pressed" 
                      GeneratedDuration="0:0:0.01" />

    <!--Take one half second to trasition 
        to the MouseOver state.-->
    <VisualTransition To="MouseOver" 
                      GeneratedDuration="0:0:0.5" />

    <!--Take one hundredth of a second to transition from the
        Pressed state to the MouseOver state.-->
    <VisualTransition From="Pressed" To="MouseOver" 
                      GeneratedDuration="0:0:0.01" />

    <!--Take one and a half seconds to transition from the
        MouseOver state to the Normal state. 
        Have the SolidColorBrush, BorderBrush, fade to blue, 
        then to yellow, and then to black in that time.-->
    <VisualTransition From="MouseOver" To="Normal" 
                      GeneratedDuration="0:0:1.5">
      <Storyboard>
        <ColorAnimationUsingKeyFrames
          Storyboard.TargetProperty="Color"
          Storyboard.TargetName="BorderBrush"
          FillBehavior="HoldEnd" >

          <ColorAnimationUsingKeyFrames.KeyFrames>
            <LinearColorKeyFrame Value="Blue" 
              KeyTime="0:0:0.5" />
            <LinearColorKeyFrame Value="Yellow" 
              KeyTime="0:0:1" />
            <LinearColorKeyFrame Value="Black" 
              KeyTime="0:0:1.5" />

          </ColorAnimationUsingKeyFrames.KeyFrames>
        </ColorAnimationUsingKeyFrames>
      </Storyboard>
    </VisualTransition>
  </VisualStateGroup.Transitions>

  <!--The remainder of the VisualStateGroup is the
      same as the previous example.-->

  <VisualState x:Name="Normal" />

  <VisualState x:Name="MouseOver">
    <Storyboard>
      <ColorAnimation 
        Storyboard.TargetName="BorderBrush" 
        Storyboard.TargetProperty="Color" 
        To="Red" />

    </Storyboard>
  </VisualState>

  <VisualState x:Name="Pressed">
    <Storyboard>
      <ColorAnimation 
        Storyboard.TargetName="BorderBrush" 
        Storyboard.TargetProperty="Color" 
        To="Transparent"/>
    </Storyboard>
  </VisualState>

  <!--The Disabled state is omitted for brevity.-->

</VisualStateGroup>

Personalización de otros controles mediante la comprensión del contrato de controlCustomizing Other Controls by Understanding the Control Contract

Un control que utiliza un ControlTemplate para especificar su estructura visual (mediante el uso de FrameworkElement objetos) y el comportamiento visual (mediante el uso de VisualState objetos) usa el modelo de control de elementos.A control that uses a ControlTemplate to specify its visual structure (by using FrameworkElement objects) and visual behavior (by using VisualState objects) uses the parts control model. Muchos de los controles que se incluyen con WPFWPF 4 emplean este modelo.Many of the controls that are included with WPFWPF 4 use this model. Las partes que un ControlTemplate autor debe ser consciente de que se comunica a través del contrato de control.The parts that a ControlTemplate author needs to be aware of are communicated through the control contract. Una vez que comprende las partes de un contrato de control, puede personalizar la apariencia de cualquier control que utilice el modelo de control de elementos.When you understand the parts of a control contract, you can customize the appearance of any control that uses the parts control model.

Un contrato de control tiene tres elementos:A control contract has three elements:

  • Los elementos visuales que usa la lógica del control.The visual elements that the control's logic uses.

  • Los estados del control y el grupo al que pertenece cada estado.The states of the control and the group each state belongs to.

  • Las propiedades públicas que afectan visualmente al control.The public properties that visually affect the control.

Elementos visuales del contrato de controlVisual Elements in the Control Contract

A veces, la lógica de un control interactúa con un FrameworkElement que se encuentra en la ControlTemplate.Sometimes a control's logic interacts with a FrameworkElement that is in the ControlTemplate. Por ejemplo, el control podría controlar un evento de uno de sus elementos.For example, the control might handle an event of one of its elements. Cuando un control espera encontrar un determinado FrameworkElement en el ControlTemplate, debe transmitir esa información a la ControlTemplate autor.When a control expects to find a particular FrameworkElement in the ControlTemplate, it must convey that information to the ControlTemplate author. El control utiliza el TemplatePartAttribute para transmitir el tipo de elemento que se espera y cuál debe ser el nombre del elemento.The control uses the TemplatePartAttribute to convey the type of element that is expected, and what the name of the element should be. El Button no tiene FrameworkElement piezas en su contrato de control, pero otros controles, como el ComboBox, hacer.The Button does not have FrameworkElement parts in its control contract, but other controls, such as the ComboBox, do.

El ejemplo siguiente se muestra el TemplatePartAttribute objetos que se especifican en el ComboBox clase.The following example shows the TemplatePartAttribute objects that are specified on the ComboBox class. La lógica de ComboBox espera encontrar una TextBox denominado PART_EditableTextBox y un Popup denominado PART_Popup en su ControlTemplate.The logic of ComboBox expects to find a TextBox named PART_EditableTextBox and a Popup named PART_Popup in its ControlTemplate.

[TemplatePartAttribute(Name = "PART_EditableTextBox", Type = typeof(TextBox))]
[TemplatePartAttribute(Name = "PART_Popup", Type = typeof(Popup))]
public class ComboBox : ItemsControl
{
}
<TemplatePartAttribute(Name:="PART_EditableTextBox", Type:=GetType(TextBox))> _
<TemplatePartAttribute(Name:="Part_Popup", Type:=GetType(Popup))> _
Public Class ComboBox
    Inherits ItemsControl

End Class

El ejemplo siguiente muestra una página simplificada ControlTemplate para el ComboBox que incluye los elementos especificados por el TemplatePartAttribute objetos en el ComboBox clase.The following example shows a simplified ControlTemplate for the ComboBox that includes the elements that are specified by the TemplatePartAttribute objects on the ComboBox class.

<ControlTemplate TargetType="ComboBox">
  <Grid>
    <ToggleButton x:Name="DropDownToggle"
      HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  
      Margin="-1" HorizontalContentAlignment="Right"
      IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,
                  RelativeSource={RelativeSource TemplatedParent}}">
      <Path x:Name="BtnArrow" Height="4" Width="8" 
        Stretch="Uniform" Margin="0,0,6,0"  Fill="Black"
        Data="F1 M 300,-190L 310,-190L 305,-183L 301,-190 Z " />
    </ToggleButton>
    <ContentPresenter x:Name="ContentPresenter" Margin="6,2,25,2"
      Content="{TemplateBinding SelectionBoxItem}"
      ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
      ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}">
    </ContentPresenter>
    <TextBox x:Name="PART_EditableTextBox"
      Style="{x:Null}"
      Focusable="False"
      Background="{TemplateBinding Background}"
      HorizontalAlignment="Left" 
      VerticalAlignment="Center" 
      Margin="3,3,23,3"
      Visibility="Hidden"
      IsReadOnly="{TemplateBinding IsReadOnly}"/>

    <Popup x:Name="PART_Popup"
      IsOpen="{TemplateBinding IsDropDownOpen}">
      <Border x:Name="PopupBorder" 
        HorizontalAlignment="Stretch" Height="Auto" 
        MinWidth="{TemplateBinding ActualWidth}"
        MaxHeight="{TemplateBinding MaxDropDownHeight}"
        BorderThickness="{TemplateBinding BorderThickness}" 
        BorderBrush="Black" Background="White" CornerRadius="3">
        <ScrollViewer x:Name="ScrollViewer" BorderThickness="0" Padding="1">
          <ItemsPresenter/>
        </ScrollViewer>
      </Border>
    </Popup>

  </Grid>
</ControlTemplate>

Estados del contrato de controlStates in the Control Contract

Los estados de un control también forman parte del contrato de control.The states of a control are also a part of the control contract. El ejemplo de cómo crear un ControlTemplate para un Button se muestra cómo especificar la apariencia de un Button según sus Estados.The example of creating a ControlTemplate for a Button shows how to specify the appearance of a Button depending on its states. Crear un VisualState para cada estado especificado y todos los VisualState objetos que comparten un GroupName en un VisualStateGroup, tal y como se describe en cambiar la apariencia de un Control según su estado anteriormente en este tema.You create a VisualState for each specified state and put all VisualState objects that share a GroupName in a VisualStateGroup, as described in Changing the Appearance of a Control Depending on Its State earlier in this topic. Controles de terceros deben especificar estados mediante la TemplateVisualStateAttribute, lo que permite que herramientas de diseñador, como Expression Blend, para exponer los Estados del control para la creación de plantillas de control.Third-party controls should specify states by using the TemplateVisualStateAttribute, which enables designer tools, such as Expression Blend, to expose the control's states for authoring control templates.

Para encontrar el contrato de control de los controles que se incluyen con WPFWPF, consulte Estilos y plantillas de controles.To find the control contract for controls that are included with WPFWPF, see Control Styles and Templates.

Propiedades del contrato de controlProperties in the Control Contract

Las propiedades públicas que afectan visualmente al control también se incluyen en el contrato de control.The public properties that visually affect the control are also included in the control contract. Puede establecer estas propiedades para cambiar la apariencia del control sin crear un nuevo ControlTemplate.You can set these properties to change the appearance of the control without creating a new ControlTemplate. También puede usar el TemplateBinding extensión de marcado para enlazar propiedades de elementos que se encuentran en el ControlTemplate a las propiedades públicas definidas por el Button.You can also use the TemplateBinding markup extension to bind properties of elements that are in the ControlTemplate to public properties that are defined by the Button.

En el ejemplo siguiente se muestra el contrato de control del botón.The following example shows the control contract for the button.

[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Pressed", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Unfocused", GroupName = "FocusStates")]
[TemplateVisualState(Name = "Focused", GroupName = "FocusStates")]
public class Button : ButtonBase
{
    public static readonly DependencyProperty BackgroundProperty;
    public static readonly DependencyProperty BorderBrushProperty;
    public static readonly DependencyProperty BorderThicknessProperty;
    public static readonly DependencyProperty ContentProperty;
    public static readonly DependencyProperty ContentTemplateProperty;
    public static readonly DependencyProperty FontFamilyProperty;
    public static readonly DependencyProperty FontSizeProperty;
    public static readonly DependencyProperty FontStretchProperty;
    public static readonly DependencyProperty FontStyleProperty;
    public static readonly DependencyProperty FontWeightProperty;
    public static readonly DependencyProperty ForegroundProperty;
    public static readonly DependencyProperty HorizontalContentAlignmentProperty;
    public static readonly DependencyProperty PaddingProperty;
    public static readonly DependencyProperty TextAlignmentProperty;
    public static readonly DependencyProperty TextDecorationsProperty;
    public static readonly DependencyProperty TextWrappingProperty;
    public static readonly DependencyProperty VerticalContentAlignmentProperty;

    public Brush Background { get; set; }
    public Brush BorderBrush { get; set; }
    public Thickness BorderThickness { get; set; }
    public object Content { get; set; }
    public DataTemplate ContentTemplate { get; set; }
    public FontFamily FontFamily { get; set; }
    public double FontSize { get; set; }
    public FontStretch FontStretch { get; set; }
    public FontStyle FontStyle { get; set; }
    public FontWeight FontWeight { get; set; }
    public Brush Foreground { get; set; }
    public HorizontalAlignment HorizontalContentAlignment { get; set; }
    public Thickness Padding { get; set; }
    public TextAlignment TextAlignment { get; set; }
    public TextDecorationCollection TextDecorations { get; set; }
    public TextWrapping TextWrapping { get; set; }
    public VerticalAlignment VerticalContentAlignment { get; set; }
}
<TemplateVisualState(Name:="Normal", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="MouseOver", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="Pressed", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="Disabled", GroupName:="CommonStates")> _
<TemplateVisualState(Name:="Unfocused", GroupName:="FocusStates")> _
<TemplateVisualState(Name:="Focused", GroupName:="FocusStates")> _
Public Class Button
    Inherits ButtonBase

    Public Shared ReadOnly BackgroundProperty As DependencyProperty
    Public Shared ReadOnly BorderBrushProperty As DependencyProperty
    Public Shared ReadOnly BorderThicknessProperty As DependencyProperty
    Public Shared ReadOnly ContentProperty As DependencyProperty
    Public Shared ReadOnly ContentTemplateProperty As DependencyProperty
    Public Shared ReadOnly FontFamilyProperty As DependencyProperty
    Public Shared ReadOnly FontSizeProperty As DependencyProperty
    Public Shared ReadOnly FontStretchProperty As DependencyProperty
    Public Shared ReadOnly FontStyleProperty As DependencyProperty
    Public Shared ReadOnly FontWeightProperty As DependencyProperty
    Public Shared ReadOnly ForegroundProperty As DependencyProperty
    Public Shared ReadOnly HorizontalContentAlignmentProperty As DependencyProperty
    Public Shared ReadOnly PaddingProperty As DependencyProperty
    Public Shared ReadOnly TextAlignmentProperty As DependencyProperty
    Public Shared ReadOnly TextDecorationsProperty As DependencyProperty
    Public Shared ReadOnly TextWrappingProperty As DependencyProperty
    Public Shared ReadOnly VerticalContentAlignmentProperty As DependencyProperty

    Public Background As Brush
    Public BorderBrush As Brush
    Public BorderThickness As Thickness
    Public Content As Object
    Public ContentTemplate As DataTemplate
    Public FontFamily As FontFamily
    Public FontSize As Double
    Public FontStretch As FontStretch
    Public FontStyle As FontStyle
    Public FontWeight As FontWeight
    Public Foreground As Brush
    Public HorizontalContentAlignment As HorizontalAlignment
    Public Padding As Thickness
    Public TextAlignment As TextAlignment
    Public TextDecorations As TextDecorationCollection
    Public TextWrapping As TextWrapping
    Public VerticalContentAlignment As VerticalAlignment
End Class

Al crear un ControlTemplate, a menudo resulta más fácil empezar con una existente ControlTemplate y realizar cambios en ella.When creating a ControlTemplate, it is often easiest to begin with an existing ControlTemplate and make changes to it. Puede realizar una de las siguientes opciones para cambiar una existente ControlTemplate:You can do one of the following to change an existing ControlTemplate:

Ejemplo completoComplete Example

El ejemplo siguiente muestra toda Button ControlTemplate que se describe en este tema.The following example shows the complete ButtonControlTemplate that is discussed in this topic.

<StackPanel>
  <StackPanel.Resources>
    <Style TargetType="Button" x:Key="newTemplate">
      <!--Set the Background, Foreground, FontSize, Width, 
                  Height, Margin, and Template properties for
                  the Button.-->
      <Setter Property="Background" Value="Navy"/>
      <Setter Property="Foreground" Value="White"/>
      <Setter Property="FontSize" Value="14"/>
      <Setter Property="Width" Value="100"/>
      <Setter Property="Height" Value="40"/>
      <Setter Property="Margin" Value="10"/>
      <Setter Property="HorizontalContentAlignment" Value="Center"/>
      <Setter Property="VerticalContentAlignment" Value="Center"/>
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="Button">
            <Border x:Name="RootElement">
              <VisualStateManager.VisualStateGroups>

                <!--Define the states and transitions for the common states.
                    The states in the VisualStateGroup are mutually exclusive to
                    each other.-->
                <VisualStateGroup Name="CommonStates">

                  <!--Define the VisualTransitions that can be used when the control
                      transitions between VisualStates that are defined in the
                      VisualStatGroup.-->
                  <VisualStateGroup.Transitions>

                    <!--Take one hundredth of a second to transition to the
                        Pressed state.-->
                    <VisualTransition To="Pressed" 
                                      GeneratedDuration="0:0:0.01" />

                    <!--Take one half second to trasition to the MouseOver state.-->
                    <VisualTransition To="MouseOver" 
                                      GeneratedDuration="0:0:0.5" />

                    <!--Take one hundredth of a second to transition from the
                        Pressed state to the MouseOver state.-->
                    <VisualTransition From="Pressed" To="MouseOver" 
                                      GeneratedDuration="0:0:0.01" />

                    <!--Take one and a half seconds to transition from the
                        MouseOver state to the Normal state. 
                        Have the SolidColorBrush, BorderBrush, fade to blue, 
                        then to yellow, and then to black in that time.-->
                    <VisualTransition From="MouseOver" To="Normal" 
                                          GeneratedDuration="0:0:1.5">
                      <Storyboard>
                        <ColorAnimationUsingKeyFrames
                          Storyboard.TargetProperty="Color"
                          Storyboard.TargetName="BorderBrush"
                          FillBehavior="HoldEnd" >

                          <ColorAnimationUsingKeyFrames.KeyFrames>

                            <LinearColorKeyFrame Value="Blue" 
                              KeyTime="0:0:0.5" />
                            <LinearColorKeyFrame Value="Yellow" 
                              KeyTime="0:0:1" />
                            <LinearColorKeyFrame Value="Black" 
                              KeyTime="0:0:1.5" />

                          </ColorAnimationUsingKeyFrames.KeyFrames>
                        </ColorAnimationUsingKeyFrames>
                      </Storyboard>
                    </VisualTransition>
                  </VisualStateGroup.Transitions>

                  <!--The Normal state is the state the button is in
                      when it is not in another state from this VisualStateGroup.
                      There is no special visual behavior for this state, but
                      the VisualState must be defined in order for the button
                      to return to its initial state.-->
                  <VisualState x:Name="Normal" />

                  <!--Change the border of the button to red when the
                      mouse is over the button.-->
                  <VisualState x:Name="MouseOver">
                    <Storyboard>
                      <ColorAnimation Storyboard.TargetName="BorderBrush"     
                                      Storyboard.TargetProperty="Color"
                                      To="Red" />

                    </Storyboard>
                  </VisualState>

                  <!--Change the border of the button to Transparent when the
                      button is pressed.-->
                  <VisualState x:Name="Pressed">
                    <Storyboard >
                      <ColorAnimation Storyboard.TargetName="BorderBrush" 
                                      Storyboard.TargetProperty="Color" 
                                      To="Transparent" 
                                      />
                    </Storyboard>
                  </VisualState>

                  <!--Show the DisabledRect when the IsEnabled property on
                      the button is false.-->
                  <VisualState x:Name="Disabled">
                    <Storyboard>
                      <DoubleAnimation Storyboard.TargetName="DisabledRect" 
                                       Storyboard.TargetProperty="Opacity"
                                       To="1" Duration="0" />
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>

                <!--Define the states and transitions for the focus states.
                    The states in the VisualStateGroup are mutually exclusive to
                    each other.-->
                <VisualStateGroup x:Name="FocusStates">

                  <!--Define the VisualStates in this VistualStateGroup.-->
                  <VisualState x:Name="Focused">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames 
                        Storyboard.TargetName="FocusVisual" 
                        Storyboard.TargetProperty="Visibility" Duration
                        ="0">
                        
                        <DiscreteObjectKeyFrame KeyTime="0">
                          <DiscreteObjectKeyFrame.Value>
                            <Visibility>Visible</Visibility>
                          </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                      </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>
                  <VisualState x:Name="Unfocused">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames 
                        Storyboard.TargetName="FocusVisual" 
                        Storyboard.TargetProperty="Visibility"
                        Duration="0">
                        
                        <DiscreteObjectKeyFrame KeyTime="0">
                          <DiscreteObjectKeyFrame.Value>
                            <Visibility>Collapsed</Visibility>
                          </DiscreteObjectKeyFrame.Value>
                        </DiscreteObjectKeyFrame>
                      </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>

              <!--Create the SolidColorBrush for the Background 
                  as an object elemment and give it a name so 
                  it can be referred to elsewhere in the control template.-->
              <Border.Background>
                <SolidColorBrush x:Name="BorderBrush" Color="Black"/>
              </Border.Background>

              <!--Create a border that has a different color by adding smaller grid.
                  The background of this grid is specified by the button's Background
                  property.-->
              <Grid Background="{TemplateBinding Background}" Margin="4">

                <!--Create a Rectangle that indicates that the
                    Button has focus.-->
                <Rectangle Name="FocusVisual" 
                           Visibility="Collapsed" Margin="2" 
                           Stroke="{TemplateBinding Foreground}" 
                           StrokeThickness="1" 
                           StrokeDashArray="1.5 1.5"/>

                <!--Use a ContentPresenter to display the Content of
                    the Button.-->
                <ContentPresenter
                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                  Margin="4,5,4,4" />

                <!--Create a rectangle that causes the button to appear
                    grayed out when it is disabled.-->
                <Rectangle x:Name="DisabledRect" 
                         Fill="#A5FFFFFF"
                         Opacity="0" IsHitTestVisible="false" />
              </Grid>
            </Border>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

  </StackPanel.Resources>

  <Button Style="{StaticResource newTemplate}" 
          Content="Button1"/>

  <Button Style="{StaticResource newTemplate}"
          Background="Purple" 
          Content="Button2" />
</StackPanel>

Vea tambiénSee also