Partilhar via


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 um 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 seja derivado de FrameworkElement ou FrameworkContentElement, como um Window ou um Button.

A maneira mais comum de declarar um estilo é como um recurso na seção Resources 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 de 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 de 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 por <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 atributo TargetType. O estilo definirá o FontSize para 15 e o FontWeight para ExtraBold. Adicione um <Setter> para cada propriedade que o estilo altera.

Aplicar um estilo implicitamente

Um Style é uma maneira conveniente de aplicar um conjunto de valores de propriedade a mais de um elemento. Por exemplo, considere os seguintes elementos 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 exemplo de estilo antes de

Você pode alterar a aparência padrão definindo propriedades, como FontSize e FontFamily, em cada elemento TextBlock diretamente. No entanto, se quiser que seus elementos TextBlock compartilhem algumas propriedades, você pode criar um Style na seção Resources do seu 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 se define a TargetType do seu estilo para o tipo TextBlock e omite o atributo x:Key, o estilo é aplicado a todos os elementos TextBlock dentro do escopo do estilo, que geralmente é o próprio arquivo XAML.

Agora, os elementos TextBlock aparecem da seguinte forma.

Captura de tela de amostra do estilo base

Aplicar um estilo explicitamente

Se você adicionar um atributo x:Key com valor ao estilo, o estilo não será mais aplicado implicitamente a todos os elementos do TargetType. Apenas 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 atributo x:Key.

<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 propriedade Style no elemento para o valor x:Key, 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 elemento TextBlock 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 atributo x:Key, ou seja, o único elemento afetado pelo estilo é aquele que fez referência ao estilo diretamente.

Exemplo de estilo de captura de tela de bloco de texto

Uma vez que um estilo é aplicado, explícita ou implicitamente, ele fica 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.

Você pode 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 classe StyleSelector.

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 Style do elemento. Os itens em uma coleção de recursos são do tipo Object. Portanto, você deve converter o estilo recuperado para um System.Windows.Style antes de atribuí-lo à propriedade Style. Por exemplo, o código a seguir define o estilo de um TextBlock chamado textblock1 para o estilo definido TitleText.

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

Estender um estilo

Talvez você queira que seus dois elementos TextBlock compartilhem alguns valores de propriedade, como o FontFamily e o HorizontalAlignmentcentrado. 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, como 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 TextBlock.

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

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

A seguir mostra como são os elementos TextBlock agora:

Blocos de Texto estilizados

Este estilo TitleText estende o estilo que foi criado para o tipo TextBlock, referenciado 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 chamado Header1 e você quisesse estender esse estilo, usaria BasedOn="{StaticResource Header1}".

Relação entre a propriedade TargetType e o atributo x:Key

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

Além de fornecer um valor padrão para o x:Key, a propriedade TargetType especifica o tipo ao qual as propriedades setter se aplicam. Se você não especificar um TargetType, deverá qualificar as propriedades em seus objetos Setter 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 WPF consistem em uma combinação de outros controles WPF. Se você criar um estilo que se aplique a todos os controles de um tipo, poderá obter resultados inesperados. Por exemplo, se você criar um estilo direcionado ao tipo TextBlock em um Window, o estilo será aplicado a todos os controles TextBlock na janela, mesmo que o TextBlock faça parte de outro controle, como um ListBox.

Ver também