Compartir a través de


Estilos XAML

El marco XAML te permite personalizar la apariencia de tus aplicaciones de varias maneras. Los estilos te permiten establecer propiedades de control y reusar esa configuración para mantener un aspecto uniforme en varios controles.

WinUI y estilos

A partir de WinUI 2.2, hemos utilizado WinUI para ofrecer nuevas actualizaciones de estilo visual en nuestros componentes de UI. Si observa que la interfaz de usuario no se actualiza a los estilos más recientes, asegúrese de actualizar al paquete más reciente NuGet de WinUI.

A partir de WinUI 2.6, proporcionamos nuevos estilos para la mayoría de los controles y un nuevo sistema de control de versiones que le permitirá volver a los estilos de control anteriores si fuera necesario. Le animamos a usar los nuevos estilos, ya que pueden coincidir mejor con la dirección de diseño de Windows. Sin embargo, si el escenario no puede admitir los nuevos estilos, las versiones anteriores siguen estando disponibles.

Puede cambiar la versión de estilo estableciendo la ControlsResourcesVersion propiedad en XamlControlsResources que se incluye en Application.Resources cuando se usa WinUI versión 2. ControlsResourcesVersion tiene como valor predeterminado el valor de enumeración Version2.

Establecer este valor en Version1 hace que XamlControlsResources cargue las versiones anteriores de estilo en lugar de los nuevos estilos que usa la versión más reciente de WinUI. No se admite el cambio de esta propiedad en tiempo de ejecución y la funcionalidad de recarga activa de VisualStudio no funcionará; sin embargo, después de volver a compilar la aplicación, observará que los estilos de control cambian.

<Application.Resources>
    <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" 
                           ControlsResourcesVersion="Version1"/>
</Application.Resources>

Conceptos básicos del estilo

Use estilos para extraer la configuración de propiedades visuales en recursos reutilizables. Este es un ejemplo en el que se muestran tres botones con un estilo que establece las propiedades BorderBrush, BorderThickness y Foreground. Al aplicar un estilo, puede hacer que los controles aparezcan iguales sin tener que establecer estas propiedades en cada control por separado.

Captura de pantalla de tres botones con estilo organizados en paralelo.

Puede definir un estilo insertado en el XAML para un control, o como un recurso reutilizable. Defina recursos en el archivo XAML de una página individual, en el archivo App.xaml o en un archivo XAML de diccionario de recursos independiente. Un archivo XAML de diccionario de recursos se puede compartir entre aplicaciones, además se puede combinar más de un diccionario de recursos en una sola aplicación. Cuando se define el recurso, determina el ámbito en el que se puede usar. Los recursos de nivel de página solo están disponibles en la página donde se definen. Si los recursos con la misma clave se definen en App.xaml y en una página, el recurso de la página invalida el recurso en App.xaml. Si un recurso se define en un archivo de diccionario de recursos diferente, su ámbito se determina por el lugar donde se hace referencia al diccionario de recursos.

En la definición de Style, necesitas un atributo TargetType y una colección de uno o más elementos Setter. El atributo TargetType es una cadena que especifica un tipo FrameworkElement al que aplicarle el estilo. El valor TargetType debe especificar un tipo derivado de FrameworkElement definido por Windows Runtime o un tipo personalizado que esté disponible en un ensamblado al que se hace referencia. Si intenta aplicar un estilo a un control y el tipo del control no coincide con el atributo TargetType del estilo que intenta aplicar, se produce una excepción.

Cada elemento Setter requiere una propiedad Property y una propiedad Value. Esta configuración de propiedad indica a qué propiedad de control se aplica la configuración y el valor que se va a establecer para esa propiedad. Puede establecer Setter.Value con sintaxis de elemento de atributo o propiedad. El XAML aquí muestra el estilo aplicado a los botones mostrados anteriormente. En este XAML, los dos primeros elementos Setter usan la sintaxis de atributo, pero el último Setter, para la propiedad BorderBrush, usa la sintaxis de elemento de propiedad. El ejemplo no usa el atributo x:Key, por lo que el estilo se aplica implícitamente a los botones. La aplicación de estilos implícita o explícitamente se explica en la sección siguiente.

<Page.Resources>
    <Style TargetType="Button">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="BorderBrush" >
            <Setter.Value>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

<StackPanel Orientation="Horizontal">
    <Button Content="Button"/>
    <Button Content="Button"/>
    <Button Content="Button"/>
</StackPanel>

Aplicar un estilo implícito o explícito

Si define un estilo como recurso, hay dos maneras de aplicarlo a los controles:

Si un estilo contiene el atributo x:Key, solo puedes aplicarlo a un control mediante el establecimiento de la propiedad Style del control en el estilo con clave. Por el contrario, un estilo sin un atributo x:Key se aplica automáticamente a todos los controles de su tipo de destino, que de lo contrario no tiene una configuración de estilo explícita.

Estos son dos botones que muestran estilos implícitos y explícitos.

botones de estilo implícito y explícito.

En este ejemplo, el primer estilo tiene un atributo x:Key y su tipo de destino es Botón. La propiedad Style del primer botón se establece en esta clave, por lo que este estilo se aplica de manera explícita. El segundo estilo se aplica implícitamente al segundo botón porque su tipo de destino es Botón y el estilo no tiene un atributo x:Key.

<Page.Resources>
    <Style x:Key="PurpleStyle" TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="Foreground" Value="Purple"/>
    </Style>

    <Style TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <RotateTransform Angle="25"/>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush" Value="Green"/>
        <Setter Property="BorderThickness" Value="2"/>
        <Setter Property="Foreground" Value="Green"/>
    </Style>
</Page.Resources>

<Grid x:Name="LayoutRoot">
    <Button Content="Button" Style="{StaticResource PurpleStyle}"/>
    <Button Content="Button"/>
</Grid>

Uso en función de los estilos

Para facilitar el mantenimiento de los estilos y optimizar su reutilización, puede crear estilos que hereden de otros estilos. Usa la propiedad BasedOn para crear estilos heredados. Los estilos heredados de otros estilos deben tener como destino el mismo tipo de control o un control que se derive del tipo al que se dirige el estilo base. Por ejemplo, si un estilo base apunta a ContentControl, los estilos que estén basados en este estilo pueden apuntar a ContentControl o a tipos que deriven de ContentControl, como Button y ScrollViewer. Si un valor no se establece en función del estilo , se hereda del estilo base. Para cambiar un valor del estilo base, el estilo en el que se basa en invalida ese valor. En el siguiente ejemplo se muestra un elemento Button y un elemento CheckBox con estilos que heredan del mismo estilo base.

botones con estilo en función del estilo.

El estilo base apunta a ContentControl y establece las propiedades Height y Width. Los estilos basados en este estilo apuntan a CheckBox y Button, que derivan de ContentControl. Los estilos heredados establecen distintos colores para las propiedades BorderBrush y Foreground. (Normalmente no se coloca un borde alrededor de un CheckBox. Lo hacemos aquí para mostrar los efectos del estilo).

<Page.Resources>
    <Style x:Key="BasicStyle" TargetType="ContentControl">
        <Setter Property="Width" Value="130" />
        <Setter Property="Height" Value="30" />
    </Style>

    <Style x:Key="ButtonStyle" TargetType="Button"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Orange" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Red" />
    </Style>

    <Style x:Key="CheckBoxStyle" TargetType="CheckBox"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Blue" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Green" />
    </Style>
</Page.Resources>

<StackPanel>
    <Button Content="Button" Style="{StaticResource ButtonStyle}" Margin="0,10"/>
    <CheckBox Content="CheckBox" Style="{StaticResource CheckBoxStyle}"/>
</StackPanel>

Uso de herramientas para trabajar con estilos fácilmente

Una manera rápida de aplicar estilos a los controles es hacer clic con el botón derecho en un control en la superficie de diseño XAML de Microsoft Visual Studio y seleccionar Editar estilo o Editar plantilla (según el control en el que haga clic con el botón derecho). A continuación, puede aplicar un estilo existente seleccionando Aplicar recurso o definir un nuevo estilo seleccionando Crear vacío. Si crea un estilo vacío, tiene la opción de definirlo en la página, en el archivo App.xaml o en un diccionario de recursos independiente.

Estilo ligero

Por norma general, los pinceles del sistema se reemplazan en el nivel de página o aplicación y, en cualquier caso, la sustitución del color afectará a todos los controles que hacen referencia a ese pincel. Además, en XAML, muchos controles pueden hacer referencia al mismo pincel del sistema.

Captura de pantalla de dos botones: uno en su estado de reposo y otro con un estilo ligero aplicado.

<Page.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Light">
                 <SolidColorBrush x:Key="ButtonBackground" Color="Transparent"/>
                 <SolidColorBrush x:Key="ButtonForeground" Color="MediumSlateBlue"/>
                 <SolidColorBrush x:Key="ButtonBorderBrush" Color="MediumSlateBlue"/>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
</Page.Resources>

Para estados como PointerOver (el mouse se mantiene sobre el botón), PointerPressed (se ha invocado el botón) o Deshabilitado (el botón no se puede interactuar). Estas terminaciones se agregan a los nombres de estilos ligeros originales: ButtonBackgroundPointerOver, ButtonForegroundPressed, ButtonBorderBrushDisabled, etc. Modificar esos pinceles también, asegurará de que los controles estén coloreados de forma coherente con el tema de la aplicación.

Al colocar estas anulaciones de pincel en el nivel App.Resources, se modificarán todos los botones de toda la aplicación, en lugar de en una sola página.

Estilo por control

En otros casos, solo se desea cambiar un único control en una página para que tenga un aspecto determinado, sin modificar ninguna otra versión de ese control:

Captura de pantalla de tres botones con estilo organizados apilados uno encima del otro.

<CheckBox Content="Normal CheckBox" Margin="5"/>
<CheckBox Content="Special CheckBox" Margin="5">
    <CheckBox.Resources>
        <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary x:Key="Light">
                    <SolidColorBrush x:Key="CheckBoxForegroundUnchecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxForegroundChecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked"
                        Color="White"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked"  
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked"
                        Color="Purple"/>
                </ResourceDictionary>
            </ResourceDictionary.ThemeDictionaries>
        </ResourceDictionary>
    </CheckBox.Resources>
</CheckBox>
<CheckBox Content="Normal CheckBox" Margin="5"/>

Esto solo afectaría a esa "CheckBox especial" en la página donde existía ese control.

Controles personalizados

Cuando cree sus propios controles personalizados que puedan estar alineados visualmente o funcionalmente con nuestros controles integrados, considere la posibilidad de usar recursos de estilo implícito y estilo ligero para definir el contenido personalizado. Puede usar los recursos directamente o crear un alias para el recurso.

Usar recursos de control directamente

Por ejemplo, si va a escribir un control similar a un botón, puede hacer que el control haga referencia directamente a los recursos del botón de la siguiente manera:

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource ButtonBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}" />
</Style>

Asignar alias a los recursos de control con nuevos nombres

Como alternativa, si prefiere crear sus propios recursos, debe aplicar un alias a esos nombres personalizados para nuestros recursos de estilo ligero predeterminados.

Por ejemplo, el estilo del control personalizado puede tener definiciones de recursos especiales:

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource MyCustomControlBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource MyCustomControlBorderBrush}"/>
</Style>

En su diccionario de recursos o definición principal, enlazaría los recursos de estilo ligero con sus recursos personalizados:

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>        
    <ResourceDictionary x:Key="Light">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

Es necesario que use un ThemeDictionary que se duplica tres veces para controlar los tres cambios de tema diferentes correctamente (Default, Light, HighContrast).

Precaución

Si asigna un recurso de estilo Lightweight a un nuevo alias y también vuelve a definir el recurso de estilo Lightweight, es posible que la personalización no se aplique si la búsqueda de recursos no está en el orden correcto. Por ejemplo, si invalida ButtonBackground en un lugar que se busca antes de que se encuentre MyCustomControlBackground, se omitirá la invalidación.

Evitar controles de cambios de estilo

WinUI 2.2 o posterior incluye nuevos estilos y plantillas para los controles WinUI y del sistema.

La mejor manera de mantenerse al día con nuestros últimos estilos visuales es usar el paquete WinUI 2 más reciente y evitar estilos y plantillas personalizados (también conocidos como re-plantillado). Los estilos siguen siendo una manera cómoda de aplicar un conjunto de valores de forma coherente entre los controles de la aplicación. Al hacerlo, asegúrese de basarse en nuestros estilos más recientes.

Para los controles del sistema que usan estilos WinUI (espacio de nombres Windows.UI.Xaml.Controls), establezca BasedOn="{StaticResource Default<ControlName>Style}", donde <ControlName> es el nombre del control. Por ejemplo:

<Style TargetType="TextBox" BasedOn="{StaticResource DefaultTextBoxStyle}">
    <Setter Property="Foreground" Value="Blue"/>
</Style>

Para los controles WinUI 2 (espacio de nombres Microsoft.UI.Xaml.Controls), el estilo predeterminado se define en los metadatos, por lo que se omite BasedOn.

Controles derivados

Si deriva un control personalizado de un control XAML existente, no obtendrá los estilos WinUI 2 de forma predeterminada. Para aplicar los estilos WinUI 2:

  • Cree un nuevo estilo con su TargetType establecido en el control personalizado.
  • Base el estilo en el estilo predeterminado del control del que se deriva.

Un escenario común para esto es derivar un nuevo control de ContentDialog. En este ejemplo se muestra cómo crear un nuevo estilo que aplica DefaultContentDialogStyle al cuadro de diálogo personalizado.

<ContentDialog
    x:Class="ExampleApp.SignInContentDialog"
    ... >

    <ContentDialog.Resources>
        <Style TargetType="local:SignInContentDialog" BasedOn="{StaticResource DefaultContentDialogStyle}"/>
        ...
    </ContentDialog.Resources> 
    <!-- CONTENT -->
</ContentDialog>        

La propiedad de plantilla

Se puede usar un establecedor de estilo para la propiedad Template de Control. De hecho, esto conforma la mayor parte de un estilo XAML típico y los recursos XAML de una aplicación. Esto se describe con más detalle en el tema Plantillas de control.