Partilhar via


Estilos de XAML

É possível personalizar a aparência de seus aplicativos de muitas formas usando a estrutura XAML. Os estilos permitem definir propriedades de controle e reutilizar essas configurações para criar uma aparência consistente em vários controles.

WinUI e estilos

A partir da WinUI 2.2, usamos a WinUI para fornecer novas atualizações de estilo visual em nossos componentes de interface do usuário. Se você notar que sua interface do usuário não está atualizando para os estilos mais recentes, certifique-se de atualizar para o pacote NuGet WinUI mais recente.

A partir da WinUI 2.6, fornecemos novos estilos para a maioria dos controles e um novo sistema de controle de versão que permite reverter para os estilos de controle anteriores, se necessário. Recomendamos que você use os novos estilos, pois eles correspondem melhor à direção de design do Windows. Porém, se o cenário não puder oferecer suporte aos novos estilos, as versões anteriores ainda estarão disponíveis.

Você pode alterar a versão do estilo definindo a propriedade ControlsResourcesVersion na XamlControlsResources que você inclui no seu Application.Resources ao usar a WinUI versão 2. ControlsResourcesVersion usa por padrão o valor enum Version2.

Definir esse valor como Version1 faz com que XamlControlsResources carregue as versões de estilo anteriores em vez dos novos estilos usados pela versão mais recente do WinUI. Não há suporte para a alteração dessa propriedade em runtime e a funcionalidade de recarga frequente do VisualStudio não funcionará; no entanto, depois de reconstruir seu aplicativo, você verá os estilos de controle mudarem.

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

Noções básicas de estilo

Use estilos para extrair configurações de propriedade visual em recursos reutilizáveis. Aqui está um exemplo que mostra 3 botões com um estilo que define as propriedades BorderBrush, BorderThickness e Foreground. Ao aplicar um estilo, você pode fazer com que os controles pareçam iguais sem precisar definir essas propriedades em cada controle separadamente.

Captura de tela de três botões estilizados dispostos lado a lado.

Você pode definir um estilo em linha no XAML para um controle ou como um recurso reutilizável. Defina recursos no arquivo XAML de uma página individual, no arquivo App.xaml ou em um arquivo XAML de dicionário de recursos separado. Um arquivo XAML de dicionário de recursos pode ser compartilhado entre aplicativos e mais de um dicionário de recursos pode ser mesclado em um único aplicativo. Onde o recurso é definido determina o escopo no qual ele pode ser usado. Os recursos no nível da página estão disponíveis somente na página em que estão definidos. Se os recursos com a mesma chave forem definidos em App.xaml e em uma página, o recurso na página substituirá o recurso em App.xaml. Se um recurso estiver definido em um arquivo de dicionário de recurso separado, seu escopo será determinado pela referência de onde partiu o dicionário do recurso.

Na definição de Style, você precisa de um atributo TargetType e de uma coleção de um ou mais elementos Setter. O atributo TargetType é uma cadeia de caracteres que especifica um tipo FrameworkElement ao qual aplicar o estilo. O valor TargetType deve especificar um tipo derivado de FrameworkElement-definido pelo Runtime do Windows ou um tipo personalizado disponível em um assembly referenciado. Se você tentar aplicar um estilo a um controle e o tipo do controle não corresponder ao atributo TargetType do estilo que você está tentando aplicar, ocorrerá uma exceção.

Cada elemento Setter requer uma Property e um Value. Essas configurações de propriedade indicam a qual propriedade de controle a configuração se aplica e o valor a ser definido para a propriedade. Você pode definir o Setter.Value com a sintaxe do atributo ou do elemento de propriedade. O XAML aqui mostra o estilo aplicado aos botões mostrado anteriormente. Nesse XAML, os dois primeiros elementos Setter usam a sintaxe de atributos, mas o último Setter para a propriedade BorderBrush usa a sintaxe de elementos de propriedade. O exemplo não usa o atributo x:Key, portanto, o estilo é aplicado implicitamente aos botões. A aplicação implícita ou explícita de estilos é explicada na próxima seção.

<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 um estilo implícito ou explícito

Se você definir um estilo como um recurso, há duas maneiras de aplicá-lo aos seus controles:

Se um estilo contiver o atributo x:Key, você só poderá aplicá-lo a um controle definindo a propriedade Style do controle como o estilo com chave. Por outro lado, um estilo sem um atributo x:Key é aplicado automaticamente a cada controle do seu tipo de destino, que não tem uma configuração de estilo explícita.

Aqui estão dois botões que demonstram estilos implícitos e explícitos.

botões com estilo implícito e explícito.

Neste exemplo, o primeiro estilo tem um atributo x:Key, e seu tipo de destino é Button. A propriedade Style do primeiro botão é definida para essa chave, de maneira que esse estilo é aplicado explicitamente. O segundo estilo é aplicado implicitamente ao segundo botão porque seu tipo de destino é Botão e o estilo não tem um 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>

Usar estilos com base em

Para facilitar a manutenção dos estilos e otimizar a reutilização de estilos, você pode criar estilos que herdam traços de outros estilos. Você usa a propriedade BasedOn para criar estilos herdados. Os estilos que herdam de outros estilos devem ter como destino o mesmo tipo de controle ou um controle derivado do tipo direcionado pelo estilo base. Por exemplo, se um estilo base tiver como destino ContentControl, estilos baseados nesse estilo poderão ter como alvo ContentControl ou tipos derivados de ContentControl, como Button e ScrollViewer. Se um valor não estiver definido no estilo com base em, ele será herdado do estilo base. Para alterar um valor do estilo base, o estilo com base em substitui esse valor. O próximo exemplo mostra um Button e uma CheckBox com estilos herdados do mesmo estilo base.

botões estilizados usando com estilos com base em.

O estilo base tem como destino ContentControl e define as propriedades Height e Width. Os estilos baseados neste estilo têm como destino CheckBox e Button, que derivam de ContentControl. Os estilos com base em definem cores diferentes para as propriedades BorderBrush e Foreground. (Normalmente, você não coloca uma borda ao redor de um CheckBox. Fazemos isso aqui para mostrar os efeitos do 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>

Usar ferramentas para trabalhar com estilos facilmente

Uma maneira rápida de aplicar estilos aos seus controles é clicar com o botão direito em um controle na superfície de design XAML do Microsoft Visual Studio e selecionar Editar Estilo ou Editar Modelo (dependendo do controle no qual você está clicando com o botão direito). Em seguida, você pode aplicar um estilo existente selecionando Aplicar Recurso ou definir um novo estilo selecionando Criar Vazio. Se você criar um estilo vazio, terá a opção de defini-lo na página, no arquivo App.xaml ou em um dicionário de recursos separado.

Estilização leve

Substituir os pincéis do sistema é geralmente feito no nível do aplicativo ou da página e, em ambos os casos, a substituição de cor afetará todos os controles que fazem referência a esse pincel – e, em XAML, muitos controles podem referenciar o mesmo pincel de sistema.

Captura de tela de dois botões: um no estado de repouso e outro com estilo leve 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 (o mouse passa o mouse sobre o botão), PointerPressed (o botão foi invocado) ou Desativado (o botão não é interagível). Essas terminações são anexadas aos nomes de estilo Lightweight originais: ButtonBackgroundPointerOver, ButtonForegroundPressed, ButtonBorderBrushDisabled, etc. Modificar esses pincéis também garantirá que seus controles sejam coloridos de forma consistente com o tema do seu aplicativo.

Colocar essas substituições de pincel no nível App.Resources alterará todos os botões dentro de todo o aplicativo, em vez de em uma única página.

Estilização por controle

Em outros casos, alterar um único controle em uma página apenas para parecer de uma determinada forma, sem alterar quaisquer outras versões desse controle, é desejado:

Captura de tela de três botões estilizados, empilhados uns sobre os outros.

<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"/>

Isso só afetaria uma "Caixa de Seleção Especial" na página onde esse controle existia.

Controles personalizados

Quando você estiver criando seus próprios controles personalizados que podem estar alinhados visualmente e/ou funcionalmente com nossos controles internos, considere usar o estilo implícito e os recursos de estilo leve para definir seu conteúdo personalizado. Você pode usar os recursos diretamente ou criar um novo alias para o recurso.

Usar recursos de controle diretamente

Por exemplo, se estiver escrevendo um controle que se parece com um Botão, você poderá fazer com que seu controle faça referência aos recursos do botão diretamente, desta forma:

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

Aliasing de recursos de controle para novos nomes

Como alternativa, se você preferir criar seus próprios recursos, você deve criar alias desses nomes personalizados para nossos recursos de estilo Lightweight padrão.

Por exemplo, o estilo do controle personalizado pode ter definições de recursos especiais:

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

No Dicionário de Recursos ou na definição principal, você conectaria os recursos de estilo Lightweight aos 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>

É necessário que você use um ThemeDictionary que é duplicado três vezes para manipular as três alterações de tema diferentes corretamente (Default, Light, HighContrast).

Cuidado

Se você atribuir um recurso de estilo Lightweight a um novo alias e também redefinir o recurso de estilo Lightweight, sua personalização poderá não ser aplicada se a pesquisa de recursos não estiver na ordem correta. Por exemplo, se você substituir ButtonBackground em um spot que é pesquisado antes de MyCustomControlBackground ser encontrado, a substituição será perdida.

Evite reestilizar controles

O WinUI 2.2 ou posterior inclui novos estilos e modelos para WinUI e controles do sistema.

A melhor maneira de se manter atualizado com nossos estilos visuais mais recentes é usar o pacote WinUI 2 mais recente e evitar estilos e modelos personalizados (também conhecido como remodelagem). Os estilos ainda são uma maneira conveniente de aplicar um conjunto de valores de forma consistente entre controles em seu aplicativo. Ao fazer isso, certifique-se de se basear em nossos estilos mais recentes.

Para controles do sistema que usam estilos WinUI (namespace Windows.UI.Xaml.Controls), defina BasedOn="{StaticResource Default<ControlName>Style}", onde<ControlName> é o nome do controle. Por exemplo:

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

Para controles do WinUI 2 (namespace Microsoft.UI.Xaml.Controls), o estilo padrão é definido nos metadados, portanto, omita BasedOn.

Controles derivados

Se você derivar um controle personalizado de um controle XAML existente, ele não obterá os estilos do WinUI 2 por padrão. Para aplicar os estilos do WinUI 2:

  • Crie um novo Estilo com seu TargetType definido para seu controle personalizado.
  • Baseie o Estilo no estilo padrão do controle do qual você derivou.

Um cenário comum para isso é derivar um novo controle de ContentDialog. Este exemplo mostra como criar um novo Style que se aplica DefaultContentDialogStyle à sua caixa de diálogo personalizada.

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

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

A propriedade do modelo

Um setter de estilo pode ser usado para a propriedade Template de um Control e, na verdade, isso compõe a maior parte de um estilo XAML típico e dos recursos XAML de um aplicativo. Isso é discutido em mais detalhes no tópico Modelos de controle.