Como criar um estilo para um controle (WPF .NET)

Com o Windows Presentation Foundation (WPF), você pode personalizar a aparência de um controle existente com seu próprio estilo reutilizável. Os estilos podem ser aplicados globalmente ao seu aplicativo, janelas e páginas ou diretamente aos controles.

Criar um estilo

Você pode pensar em a Style como uma maneira conveniente de aplicar um conjunto de valores de propriedade a um ou mais elementos. Você pode usar um estilo em qualquer elemento que derive de FrameworkElement ou FrameworkContentElement como um Window ou um Button.

A maneira mais comum de declarar um estilo é como um recurso na Resources seção em um arquivo XAML. Como os estilos são recursos, eles obedecem às mesmas regras de escopo que se aplicam a todos os recursos. Simplificando, onde você declara um estilo afeta onde o estilo pode ser aplicado. Por exemplo, se você declarar o estilo no elemento raiz do arquivo XAML de definição do aplicativo, o estilo poderá ser usado em qualquer lugar do aplicativo.

<Application x:Class="IntroToStylingAndTemplating.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:IntroToStylingAndTemplating"
             StartupUri="WindowExplicitStyle.xaml">
    <Application.Resources>
        <ResourceDictionary>
            
            <Style x:Key="Header1" TargetType="TextBlock">
                <Setter Property="FontSize" Value="15" />
                <Setter Property="FontWeight" Value="ExtraBold" />
            </Style>
            
        </ResourceDictionary>
    </Application.Resources>
</Application>

Se você declarar o estilo em um dos arquivos XAML do aplicativo, o estilo poderá ser usado somente nesse arquivo XAML. Para obter mais informações sobre regras de escopo para recursos, consulte Visão geral dos recursos XAML.

<Window x:Class="IntroToStylingAndTemplating.WindowSingleResource"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:IntroToStylingAndTemplating"
        mc:Ignorable="d"
        Title="WindowSingleResource" Height="450" Width="800">
    <Window.Resources>
        
        <Style x:Key="Header1" TargetType="TextBlock">
            <Setter Property="FontSize" Value="15" />
            <Setter Property="FontWeight" Value="ExtraBold" />
        </Style>
        
    </Window.Resources>
    <Grid />
</Window>

Um estilo é composto de <Setter> elementos filho que definem propriedades nos elementos aos quais o estilo é aplicado. No exemplo acima, observe que o estilo está definido para ser aplicado a TextBlock tipos por meio do TargetType atributo. O estilo definirá o FontSize para 15 e o FontWeight para ExtraBold. Adicione um <Setter> para cada propriedade que o estilo muda.

Aplicar um estilo implicitamente

A Style é uma maneira conveniente de aplicar um conjunto de valores de propriedade a mais de um elemento. Por exemplo, considere os elementos a seguir TextBlock e sua aparência padrão em uma janela.

<StackPanel>
    <TextBlock>My Pictures</TextBlock>
    <TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>

Captura de tela de amostra de estilo antes

Você pode alterar a aparência padrão definindo propriedades, como FontSize e FontFamily, em cada TextBlock elemento diretamente. No entanto, se você quiser que seus TextBlock elementos compartilhem algumas propriedades, poderá criar um Style na Resources seção do arquivo XAML, conforme mostrado aqui.

<Window.Resources>
    <!--A Style that affects all TextBlocks-->
    <Style TargetType="TextBlock">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="FontFamily" Value="Comic Sans MS"/>
        <Setter Property="FontSize" Value="14"/>
    </Style>
</Window.Resources>

Quando você define o TargetType estilo como o TextBlock tipo e omite o x:Key atributo, o estilo é aplicado a todos os TextBlock elementos com escopo para o estilo, que geralmente é o próprio arquivo XAML.

Agora os TextBlock elementos aparecem da seguinte forma.

Estilo base de captura de tela de amostra de estilo

Aplicar um estilo explicitamente

Se você adicionar um x:Key atributo com valor ao estilo, o estilo não será mais aplicado implicitamente a todos os elementos do TargetType. Somente os elementos que fazem referência explícita ao estilo terão o estilo aplicado a eles.

Aqui está o estilo da seção anterior, mas declarado com o x:Key atributo.

<Window.Resources>
    <Style x:Key="TitleText" TargetType="TextBlock">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="FontFamily" Value="Comic Sans MS"/>
        <Setter Property="FontSize" Value="14"/>
    </Style>
</Window.Resources>

Para aplicar o estilo, defina a Style propriedade no elemento como o x:Key valor, usando uma extensão de marcação StaticResource, conforme mostrado aqui.

<StackPanel>
    <TextBlock Style="{StaticResource TitleText}">My Pictures</TextBlock>
    <TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>

Observe que o primeiro TextBlock elemento tem o estilo aplicado a ele, enquanto o segundo elemento TextBlock permanece inalterado. O estilo implícito da seção anterior foi alterado para um estilo que declarava o x:Key atributo, ou seja, o único elemento afetado pelo estilo é aquele que fazia referência direta ao estilo.

Textblock de captura de tela de exemplo de estilo

Depois que um estilo é aplicado, explícita ou implicitamente, ele se torna selado e não pode ser alterado. Se você quiser alterar um estilo que foi aplicado, crie um novo estilo para substituir o existente. Para obter mais informações, consulte a propriedade IsSealed.

É possível criar um objeto que escolhe um estilo para aplicar com base na lógica personalizada. Para obter um exemplo, consulte o exemplo fornecido para a StyleSelector classe.

Aplicar um estilo programaticamente

Para atribuir um estilo nomeado a um elemento programaticamente, obtenha o estilo da coleção de recursos e atribua-o à propriedade do Style elemento. Os itens em uma coleção de recursos são do tipo Object. Portanto, você deve converter o estilo recuperado em um System.Windows.Style antes de atribuí-lo à Style propriedade. Por exemplo, o código a seguir define o estilo de um TextBlock nomeado textblock1 para o estilo TitleTextdefinido .

textblock1.Style = (Style)Resources["TitleText"];
textblock1.Style = CType(Resources("TitleText"), Windows.Style)

Estender um estilo

Talvez você queira que seus dois TextBlock elementos compartilhem alguns valores de propriedade, como o e o FontFamily centralizado HorizontalAlignment. Mas você também deseja que o texto Minhas Imagens tenha algumas propriedades adicionais. Você pode fazer isso criando um novo estilo baseado no primeiro estilo, conforme mostrado aqui.

<Window.Resources>
    <!-- .... other resources .... -->

    <!--A Style that affects all TextBlocks-->
    <Style TargetType="TextBlock">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="FontFamily" Value="Comic Sans MS"/>
        <Setter Property="FontSize" Value="14"/>
    </Style>
    
    <!--A Style that extends the previous TextBlock Style with an x:Key of TitleText-->
    <Style BasedOn="{StaticResource {x:Type TextBlock}}"
           TargetType="TextBlock"
           x:Key="TitleText">
        <Setter Property="FontSize" Value="26"/>
        <Setter Property="Foreground">
            <Setter.Value>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <LinearGradientBrush.GradientStops>
                        <GradientStop Offset="0.0" Color="#90DDDD" />
                        <GradientStop Offset="1.0" Color="#5BFFFF" />
                    </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

Em seguida, aplique o estilo a um TextBlockarquivo .

<StackPanel>
    <TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
    <TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>

Esse TextBlock estilo agora está centralizado, usa uma Comic Sans MS fonte com um tamanho de e a cor do primeiro plano definida como LinearGradientBrush mostrada 26no exemplo. Observe que ele substitui o FontSize valor do estilo base. Se houver mais de um Setter apontando para a mesma propriedade em um Style, o que é declarado Setter por último tem precedência.

O seguinte mostra como os TextBlock elementos agora se parecem:

TextBlocks estilizados

Esse TitleText estilo estende o estilo que foi criado para o tipo, referenciado TextBlock com BasedOn="{StaticResource {x:Type TextBlock}}". Você também pode estender um estilo que tenha um x:Key usando o x:Key do estilo. Por exemplo, se houvesse um estilo nomeado Header1 e você quisesse estender esse estilo, usaria BasedOn="{StaticResource Header1}".

Relação da propriedade TargetType e do atributo x:Key

Como mostrado anteriormente, definir a TargetType propriedade como TextBlock sem atribuir o estilo an x:Key faz com que o estilo seja aplicado a todos os TextBlock elementos. Nesse caso, o x:Key é definido implicitamente como {x:Type TextBlock}. Isso significa que, se você definir explicitamente o x:Key valor como algo diferente de {x:Type TextBlock}, o Style não será aplicado a todos os TextBlock elementos automaticamente. Em vez disso, você deve aplicar o estilo (usando o x:Key valor) aos TextBlock elementos explicitamente. Se o seu estilo estiver na seção de recursos e você não definir a TargetType propriedade em seu estilo, deverá definir o x:Key atributo.

Além de fornecer um valor padrão para o , a TargetType propriedade especifica o tipo ao qual as x:Keypropriedades do setter se aplicam. Se você não especificar um TargetType, deverá qualificar as propriedades em seus Setter objetos com um nome de classe usando a sintaxe Property="ClassName.Property". Por exemplo, em vez de definir Property="FontSize", você deve definir Property como "TextBlock.FontSize" ou "Control.FontSize".

Observe também que muitos controles do WPF consistem em uma combinação de outros controles do WPF. Caso você crie um estilo que se aplica a todos os controles de um tipo, pode obter resultados inesperados. Por exemplo, se você criar um estilo direcionado ao TextBlock tipo em um Window, o estilo será aplicado a todos os TextBlock controles na janela, mesmo que faça TextBlock parte de outro controle, como um ListBox.

Confira também