Styling and Templating

Estilos e modelagem de Windows Presentation Foundation (WPF) referem-se a um conjunto de recursos (estilos, modelos, disparadores e storyboards) que permitem que os criadores de um aplicativo, documento ou interface do usuário (UI) criem efeitos visualmente atraentes e padronizem uma aparência consistente para seu produto. Embora um autor ou designer pode personalizar aparência extensivamente em uma base por aplicativo, um modelo de estilo e modelagem forte é necessário para permitir o compartilhamento de aparência dentro e entre aplicativos e manutenção. Windows Presentation Foundation (WPF) fornece esse modelo.

Outro recurso da estratégia de aplicação de estilos do WPF é a separação entre apresentação e lógica. Isso significa que os designers podem trabalhar na aparência de um aplicativo usando apenas XAML ao mesmo tempo que os desenvolvedores estão trabalhando na lógica de programação usando C# ou Visual Basic.

Esta visão geral discute o aplicativo Introdução Paraos estilos e exemplo de modelParagem, que tem dois elementos TextBlock e um controle ListBox que está vinculado a uma lista de imagens:

ListView com estilo

Esta visão geral enfoca os aspectos de aplicação de estilos e modelos do aplicativo e não discute nenhum conceito referente a associação de dados. Para obter mais informações sobre a associação de dados, consulte Revisão de Associação de Dados.

Além disso, é importante compreender os recursos, que são o que permitem que estilos e modelos sejam reutilizados. Para obter mais informações sobre recursos, consulte Visão geral sobre Recursos.

Este tópico contém as seguintes seções.

  • Conceitos básicos sobre estilos
  • Modelos de dados
  • Modelos de Controle
  • Disparadores
  • Recursos compartilhados e temas
  • Tópicos relacionados

Conceitos básicos sobre estilos

Você pode pensar em uma Style como uma maneira conveniente aplicar um conjunto de valores de propriedade sobre mais de um elemento. Por exemplo, considere os seguintes elementos TextBlock e sua aparência padrão:

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

Captura de tela de exemplo de aplicação de estilo

Você pode alterar a aparência padrão definindo as propriedades como FontSize e FontFamily em cada elemento TextBlock diretamente. No entanto, se você quiser que os elementos TextBlock compartilhem algumas propriedades, você pode criar uma Style na seção Resources 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 do seu estilo como o tipo TextBlock, o estilo é aplicado sobre todos os elementos TextBlock na janela.

Agora, os elementos TextBlock aparecem da seguinte maneira:

Captura de tela de exemplo de aplicação de estilo

Esta seção contém as seguintes subseções.

  • Estendendo estilos
  • Relação entre a propriedade TargetType e o atributo x:Key
  • Estilos e recursos
  • Definindo estilos de forma programática
  • Ligações, recursos dinâmicos e tratadores de eventos

Estendendo estilos

Talvez você queira que seus dois elementos TextBlock compartilhem alguns valores de propriedade, como o FontFamily e o HorizontalAlignment centralizado, mas também deseje que o texto "Minhas figuras" tenha algumas propriedades adicionais. Você pode conseguir isto criando um novo estilo que é baseado no primeiro estilo, conforme mostrado aqui:

<Window.Resources>


...


<!--A Style that extends the previous TextBlock Style-->
<!--This is a "named 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>

Observe que o estilo acima recebe uma x:Key. Para aplicar o estilo, você define a propriedade Style no seu TextBlock como o valor x:Key, conforme mostrado aqui:

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

Esse estilo para TextBlock agora tem um valor de HorizontalAlignment de Center, um valor FontFamily de Comic Sans MS, um valor FontSize de 26 e um valor Foreground definido como LinearGradientBrush, conforme mostrado no exemplo. Observe que substituímos o valor FontSize do estilo de base. Se houver mais de uma Setter configurando a mesma propriedade em um Style, a precedência pertence com o Setter que é declarado por último.

Veja, a seguir, a nova aparência dos elementos TextBlock:

TextBlocks com estilo

Esse estilo TitleText estende o estilo que foi criado para o tipo TextBlock. Você também pode estender um estilo que tem uma x:Key usando o valor x:Key. Por exemplo, consulte o exemplo fornecido para a propriedade BasedOn.

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

Como mostrado no primeiro exemplo, definir a propriedade TargetType como TextBlock sem atribuir um x:Key ao estilo faz com que o estilo seja aplicado a todos os elementos TextBlock. Nesse caso, o x:Key é definida implicitamente como {x:Type TextBlock}. Isso significa que se você definir o valor x:Key explicitamente para algo que não seja {x:Type TextBlock}, o Style não é 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 o seu estilo estiver na seção recursos e você não definir a propriedade TargetType no seu estilo, então você deve fornecer um x:Key.

Além de fornecer um valor padrão para a x:Key, a propriedade TargetType especifica o tipo a que se aplicam as propriedades setter. Se você não especificar um TargetType, você deve 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".

Além disso, observe que muitos controles WPF consistem de uma combinação de outros controles WPF. Se você criar um estilo que se aplica a todos os controles de um tipo, você pode obter resultados inesperados. Por exemplo, se você criar um estilo que se aplica ao tipo TextBlock em um Window, o estilo é aplicado a todos os controles TextBlock na janela, mesmo se o TextBlock fizer parte de um outro controle, como um ListBox.

Estilos e recursos

Você pode usar um estilo em qualquer elemento que é derivado de FrameworkElement ou FrameworkContentElement. A maneira mais comum para declarar um estilo é como um recurso na seção Resources de um arquivo XAML, conforme os exemplos anteriores. Como os estilos são recursos, eles obedecem as mesmas regras de escopo que se aplicam a todos os recursos; onde você declarar um estilo afeta onde o estilo pode ser aplicado. Se, por exemplo, você declarar o estilo no elemento raiz do seu arquivo XAML de definição de aplicativo, o estilo pode ser usado em qualquer lugar no seu aplicativo. Se você criar um aplicativo de navegação e declarar o estilo em um dos arquivos XAML do aplicativo, o estilo pode ser usado somente naquele arquivo XAML. Para obter mais informações sobre regras de escopo para recursos, consulte Visão geral sobre Recursos.

Além disso, você encontrará mais informações sobre os estilos e recursos em Recursos compartilhados e temas posteriormente nesta visão geral.

Definindo estilos de forma programática

Para atribuir um estilo nomeado por meio de programação a um elemento, obtenha o estilo da coleção recursos e atribua-a à propriedade Style do elemento. Observe que os itens de uma coleção recursos são do tipo Object, portanto, você deve converter o estilo recuperado para um Style antes de atribui-lo à propriedade Style. Por exemplo, para definir o estilo TitleText definido em um TextBlock denominado textblock1, faça o seguinte:

textblock1.Style = (Style)(this.Resources["TitleText"]);

Observe que depois que um estilo tiver sido aplicado, ele é lacrado e não pode ser alterado. Se você desejar alterar dinamicamente um estilo que já foi aplicado, você deve criar 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 em lógica personalizada. Por exemplo, consulte o exemplo fornecido para a propriedade StyleSelector.

Ligações, recursos dinâmicos e tratadores de eventos

Observe que você pode usar a propriedade Setter.Value para especificar uma Ligação de marcação de extensão ou uma Extensão de marcação DynamicResource. Para obter mais informações, consulte os exemplos fornecidos para a propriedade Setter.Value.

Até o momento, só discutimos o uso de setters para definir o valor da propriedade. Você também pode especificar tratadores de eventos em um estilo. Para obter mais informações, consulte EventSetter.

Modelos de dados

Neste aplicativo de exemplo, temos um controle ListBox que está vinculado a uma lista de fotos:

<ListBox ItemsSource="{Binding Source={StaticResource MyPhotos}}"
         Background="Silver" Width="600" Margin="10" SelectedIndex="0"/>

Este ListBox, no momento, tem a seguinte aparência:

ListBox antes da aplicação de modelo

A maioria dos controles têm algum tipo de conteúdo, e esse conteúdo frequentemente vem dos dados a que você os vinculou. Neste exemplo, os dados são a lista de fotos. Em WPF, você usa um DataTemplate para definir a representação visual dos dados. Basicamente, o que você colocar em um DataTemplate determina a aparência dos dados no aplicativo.

No nosso aplicativo de exemplo, cada objeto Photo personalizado tem uma Source propriedade de tipo string que especifica o caminho do arquivo de imagem. No momento, os objetos de fotos aparecem como caminhos de arquivo.

Para que as fotos apareçam como imagens, você cria um DataTemplate como um recurso:

<Window.Resources>


...


<!--DataTemplate to display Photos as images
    instead of text strings of Paths-->
<DataTemplate DataType="{x:Type local:Photo}">
  <Border Margin="3">
    <Image Source="{Binding Source}"/>
  </Border>
</DataTemplate>


...


</Window.Resources>

Observe que a propriedade DataType é muito semelhante à propriedade TargetType de Style. Se sua DataTemplate estiver na seção recursos, quando você especifica a propriedade DataType como um tipo e não lhe atribui um x:Key, o DataTemplate é aplicado sempre que aquele tipo aparece. Você sempre tem a opção de atribuir o DataTemplate com um x:Key e, em seguida, configurá-lo como uma StaticResource para propriedades que recebem tipos DataTemplate, tal como a propriedade ItemTemplate ou a propriedade ContentTemplate.

Basicamente, o DataTemplate no exemplo acima define que sempre que houver um objeto Photo, ele deve aparecer como um Image em um Border. Com este DataTemplate, nosso aplicativo agora tem a seguinte aparência:

Imagem fotográfica

A estratégia de aplicação de modelos a dados oferece outros recursos. Por exemplo, se você estiver exibindo os dados de uma coleção que contém outras coleções usando um tipo HeaderedItemsControl, tal como um Menu ou um TreeView, há o HierarchicalDataTemplate. Outro recurso para a aplicação de modelos a dados é o DataTemplateSelector, que permite que você escolha um DataTemplate para usar com base na lógica personalizada. Para obter mais informações, consulte Visão geral sobre Templating de dados, que fornece uma discussão mais detalhada sobre os diferentes recursos de aplicação de modelos a dados.

Modelos de Controle

Esta seção contém as seguintes subseções.

  • Sem usar o ControlTemplate
  • O que é um ControlTemplate?
  • Criando um ControlTemplate
  • Propriedade IsItemsHost
  • ItemsPresenter e ContentPresenter
  • TemplateBinding

Agora que nossas fotos aparecem como imagens, vamos exibi-las horizontalmente em vez de verticalmente; desejamos fazer com que a ListBox seja horizontal.

Sem usar o ControlTemplate

Primeiro, é importante destacar que não é necessário usar o ControlTemplate para tornar a ListBox horizontal. Um ListBox tem uma propriedade ItemsPanel que permite que você defina um ItemsPanelTemplate, o modelo que controla o layout dos itens de ListBox. Uma opção é simplesmente criar um estilo ListBox e definir a propriedade ItemsPanel, como no exemplo a seguir:

<Style TargetType="ListBox">
  <Setter Property="ItemsPanel">
    <Setter.Value>
      <ItemsPanelTemplate>
        <StackPanel Orientation="Horizontal"
                    VerticalAlignment="Center"
                    HorizontalAlignment="Center"/>
      </ItemsPanelTemplate>
    </Setter.Value>
  </Setter>
</Style>

Isso funciona muito bem e nos proporciona um ListBox horizontal. Este exemplo mostra que dependendo de sua situação, pode haver outras opções além de substituir o ControlTemplate. Para esse exemplo, se quisermos um ListBox horizontal que tem propriedades adicionais, tais como cantos arredondados, então precisamos trabalhar com o ControlTemplate do ListBox.

Antes de fornecermos um exemplo para mostrar como se faz isso, é importante explicar o conceito de um ControlTemplate.

O que é um ControlTemplate?

Para a maioria dos controles, existe a aparência e o comportamento. Considere um botão: aparência é a área elevada que você pode pressionar e o comportamento é o Click evento é gerado em resposta a um clicar.

Às vezes, pode haver um controle que fornece o comportamento que você precisa, mas não a aparência que você precisa. Até agora, mostramos que você pode usar setters de estilos para definir valores de propriedade para afetar a aparência do controle. No entanto, para alterar a estrutura de um controle ou definir valores de propriedade sobre os componentes que compõem um controle, você precisará usar um ControlTemplate.

Em WPF, o ControlTemplate de um controle define a aparência do controle. Você pode alterar a estrutura e aparência de um controle definindo um novo ControlTemplate para o controle. Em muitos casos, isso lhe dará flexibilidade suficiente para que você não precise escrever seus próprios controles personalizados. Se você não definir seu próprio ControlTemplate para o controle, você fica com o modelo padrão que corresponde ao tema do sistema, que é o que dá ao controle Button sua aparência padrão.

Uma coisa para se ter em mente é que depois de criar um ControlTemplate para o controle, você está substituindo todo o ControlTemplate. Por exemplo, você pode definir, para o Button, o ControlTemplate da seguinte maneira.

Observe que o elemento ContentPresenter simplesmente marca onde deve ir o Content do Button. Discutiremos as peças diferentes em uma seção posterior.

<Style TargetType="Button">
  <!--Set to true to not get any properties from the themes.-->
  <Setter Property="OverridesDefaultStyle" Value="True"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Grid>
          <Ellipse Fill="{TemplateBinding Background}"/>
          <ContentPresenter HorizontalAlignment="Center"
                            VerticalAlignment="Center"/>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Quando isso é aplicado, o Button aparece como um Ellipse:

Exemplo de ControlTemplate de botão

Lembre-se da aparência que o Button tem quando está em foco ou pressionado faz parte da aparência padrão do botão que você está substituindo. Portanto, dependendo das suas necessidades, convém colocar em sua definição qual a aparência que o botão deve ter quando ele for pressionado. Para obter um exemplo completo, consulte Exemplo de Modelo de Controle de Botão.

Se você estiver criando um ControlTemplate, a melhor maneira para começar é usando os Exemplos de ControlTemplate. Se você realmente precisar examinar as partes que compõem de um controle, você pode dar uma olhada no arquivo de temas localizado em Temas ou você pode usar a funcionalidade Show Visual Tree de XAMLPad, um aplicativo que é instalado com o Windows Software Development Kit (SDK).

Criando um ControlTemplate

Agora vamos continuar com o nosso exemplo e criar um ControlTemplate que define um ListBox que é horizontal e tem cantos arredondados. Para substituir o ControlTemplate de um controle, defina a propriedade Template para o novo ControlTemplate.

<Style TargetType="ListBox">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ListBox">
        <Border CornerRadius="5" Background="{TemplateBinding ListBox.Background}">
          <ScrollViewer HorizontalScrollBarVisibility="Auto">
            <StackPanel Orientation="Horizontal"
                       VerticalAlignment="Center"
                       HorizontalAlignment="Center"
                       IsItemsHost="True"/>
          </ScrollViewer>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Ao conjunto o Template propriedade dessa forma, ele realmente não é diferente de conjunto outras propriedades do controle usando um Style: Você está usando um Style sistema autônomo uma ferramenta para ajudar você a conjunto o Template propriedade. Isso significa que outra maneira de definir um ControlTemplate é definir a propriedade Template diretamente no seu controle. Se você o fizer dessa maneira, você criaria um ControlTemplate na seção Resources, forneceria-lhe um x:Key, e em seguida usaria-o como um recurso estático. Por exemplo, consulte a propriedade Template.

Como você pode ver no exemplo acima, a classe ControlTemplate possui uma propriedade TargetType que é semelhante à propriedade TargetType da classe Style. No entanto, observe que ao contrário das Style e DataTemplate, objetos ControlTemplate não têm a noção de uma chave implícita. Em outras palavras, se você tiver um ControlTemplate autônomo com a propriedade TargetType definida para um tipo, o ControlTemplate não é aplicado a esse tipo automaticamente. Também observe que a propriedade TargetType é necessária em um ControlTemplate se a definição de modelo contiver uma ContentPresenter.

Faça experiências com o ControlTemplate. Por exemplo, substitua o StackPanel com um WrapPanel, defina a propriedade HorizontalScrollBarVisibility do ScrollViewer como Disabled e, em seguida, defina a largura da ListBox para 300. (O WrapPanel apenas coloca itens na próxima linha quando o espaço na primeira linha acabar. Se você não definir a propriedade HorizontalScrollBarVisibility do ScrollViewer para Disabled o espaço na primeira linha não acaba porque você pode rolar para o final. Consequentemente, o WrapPanel não quebra os itens.)

Propriedade IsItemsHost

Neste exemplo, uma propriedade importante que deve estar presente é a propriedade IsItemsHost. A propriedade IsItemsHost é usada para indicar no modelo de um ItemsControl (controles tais como ListBox que funcionam com uma lista de itens,) onde os elementos gerados devem ir. Definir a propriedade como true sobre a StackPanel significa que quaisquer itens adicionados à ListBox vão para o StackPanel. Observe que essa propriedade só funciona em tipos Panel.

ItemsPresenter e ContentPresenter

No entanto, observe que quando você especificar um painel no ControlTemplate e marcá-lo como IsItemsHost dessa maneira, o ItemsPanel não pode ser substituído pelo usuário do controle sem usar um ControlTemplate. Portanto, faça-o dessa maneira apenas se você souber que não vai querer que o painel seja substituído sem o uso de um modelo. Como alternativa, você pode usar o elemento ItemsPresenter para marcar onde os itens devem ir e, em seguida, especificar um ItemsPanelTemplate definindo a propriedade ItemsPanel. A página sobre ItemsPanelTemplate tem um exemplo que mostra como fazer isso. Para ver outro exemplo que usa o ItemsPresenter, consulte Exemplo de ControlTemplate de TreeView.

Se você estiver criando um modelo para um ContentControl tal como um Button, o elemento correspondente é o ContentPresenter. Da mesma forma, você coloca esse elemento no ControlTemplate do seu tipo ContentControl para indicar onde o conteúdo deve ser exibido, conforme demonstrado no exemplo na seção O que é um ControlTemplate?. Para outros exemplos, consulte Exemplo de Rótulo de ControlTemplate e Exemplo de um ControlTemplate ListBoxItem.

TemplateBinding

Outra coisa importante a observar no exemplo anterior é o valor Background que é definido como {TemplateBinding ListBox.Background}. Isso está simplesmente indicando que o Background do Border deve ser sincronizado com o valor Background que é definido na ListBox. Um TemplateBinding é semelhante a um Binding. Na verdade, um TemplateBinding é mais eficiente, mas menos funcional, que um Binding; usar um TemplateBinding equivale a usar um Binding com a propriedade Source definida como RelativeSource. TemplatedParent.

Usar TemplateBinding no seu ControlTemplate Quando você deseja dar ao usuário do seu controle o controle sobre os valores de certas propriedades. TemplateBinding é uma extensão de marcação que é representada por TemplateBindingExtension classe.

Você talvez tenha observado que DataTemplate e ControlTemplate são semelhantes pois ambos fazem com que seu conteúdo se torne a visualização de um objeto. Com a definição, para o ListBox, de um ControlTemplate, nosso aplicativo agora tem a seguinte aparência:

Captura de tela de exemplo de aplicação de estilo

Disparadores

Style, ControlTemplate, and DataTemplate têm uma propriedade Triggers que pode conter um conjunto de disparadores. Um disparador define propriedades ou inicia ações, tais como uma animação quando um valor da propriedade mudar ou quando um evento é gerado.

Esta seção contém as seguintes subseções.

  • Disparadores de propriedade
  • EventTriggers e Storyboards
  • MultiTriggers, DataTriggers, e MultiDataTriggers

Disparadores de propriedade

Para demonstrar como usar disparadores para definir propriedades, vamos fazer cada ListBoxItem parcialmente transparente, a menos que ele esteja marcado.

O estilo a seguir define o valor Opacity de um ListBoxItem como 0.5. Quando a propriedade IsSelected é true, no entanto, o Opacity é definida como 1.0:

<Style TargetType="ListBoxItem">
  <Setter Property="Opacity" Value="0.5" />
  <Setter Property="MaxHeight" Value="75" />
  <Style.Triggers>
    <Trigger Property="IsSelected" Value="True">
        <Setter Property="Opacity" Value="1.0" />
    </Trigger>


...


  </Style.Triggers>
</Style>

Este exemplo usa um Trigger para definir um valor da propriedade, mas observe que a classe Trigger também tem as propriedades EnterActions e ExitActions que permitem que um disparador execute ações.

Observe que nós também definimos a propriedade MaxHeight do ListBoxItem para 75. Na seguinte captura de tela, o terceiro item é o item selecionado:

ListView com estilo

EventTriggers e Storyboards

Acabamos de mostrar que um Trigger define valores de propriedade ou inicia ações com base no valor de uma propriedade. Outro tipo de disparador é o EventTrigger, que inicia um conjunto de ações com base na ocorrência de um evento. Por exemplo, os seguintes objetos EventTrigger especificam que quando o ponteiro do mouse entra no ListBoxItem, a propriedade MaxHeight anima para um valor de 90 durante um período de 0.2 segundo. Quando o mouse se move para fora do item, a propriedade retorna para o valor original durante um período de 1 Segundo. Observe como não é necessário especificar um valor To para a animação MouseLeave. Isso ocorre porque a animação é capaz de acompanhar o valor original.

<EventTrigger RoutedEvent="Mouse.MouseEnter">
  <EventTrigger.Actions>
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Duration="0:0:0.2"
          Storyboard.TargetProperty="MaxHeight"
          To="90"  />
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
  <EventTrigger.Actions>
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Duration="0:0:1"
          Storyboard.TargetProperty="MaxHeight"  />
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
</EventTrigger>

Para obter mais informações, consulte o Visão geral sobre Storyboards.

Na seguinte captura de tela, o mouse está apontando para o terceiro item:

Captura de tela de exemplo de aplicação de estilo

MultiTriggers, DataTriggers, e MultiDataTriggers

Em adição a Trigger e EventTrigger, há outros tipos de disparadores. MultiTrigger permite que você conjunto valores de propriedade baseados em várias condições. Você usa DataTrigger e MultiDataTrigger quando a propriedade de sua condição é ligada a dados.

Para o exemplo completo discutido neste resumo, consulte Introdução Paraos estilos e exemplo de modelParagem.

Recursos compartilhados e temas

Um aplicativo Windows Presentation Foundation (WPF) típico pode ter vários recursos de interface do usuário (UI) que são aplicados em todo o aplicativo. Coletivamente, esse conjunto de recursos pode ser considerado o tema para o aplicativo. Windows Presentation Foundation (WPF) oferece suporte para usuário de empacotamento recursos da interface (UI) sistema autônomo um tema usando um dicionário de recurso encapsulado sistema autônomo o ResourceDictionary classe.

Os temas Windows Presentation Foundation (WPF) são definidos usando o mecanismo para aplicação de estiloe e modelos que a Windows Presentation Foundation (WPF) expõe para personalizar a aparência de qualquer elemento.

Os recursos de temas Windows Presentation Foundation (WPF) são armazenados em dicionários de recursos incorporados. Esses dicionários de recursos devem ser incorporados em um conjunto de módulos (assembly) assinado, e podem ser incorporados no mesmo conjunto de módulos em que se encontra o código ou em um conjunto de módulos lado a lado. No caso de PresentationFramework.dll, o conjunto de módulos (assembly) que contém os controles da Windows Presentation Foundation (WPF), os recursos de tema estão em uma série de conjuntos de módulos lado a lado.

O tema torna-se o último local onde pode ser encontrado o estilo de um elemento. Normalmente, a pesquisa começará percorrendo a árvore de elementos em busca do recurso adequado, em seguida examinará a coleção de recursos do aplicativo e finalmente consultará o sistema. Isso permite que os autores dos aplicativos redefinam o estilo de qualquer objeto no nível de árvore ou de aplicativo antes de alcançar o tema.

Você pode definir os dicionários de recursos como arquivos individuais que permitem que você reutilize um tema em vários aplicativos. Você também pode criar temas permutáveis definindo vários dicionários de recursos que fornecem os mesmos tipos de recursos, mas com valores diferentes. Redefinir esses estilos ou outros recursos no nível do aplicativo é a abordagem recomendada para fazer o skinning de um aplicativo.

Para compartilhar um conjunto de recursos, incluindo estilos e modelos, entre aplicativos, você pode criar um arquivo XAML e definir um ResourceDictionary. Por exemplo, dê uma olhada na seguinte captura de tela que mostra uma parte do Estilo com ControlTemplates exemplo:

Exemplos de modelo de controle

Se você observar os arquivos XAML no exemplo, você notará que todos os arquivos contêm o seguinte:

<ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>

É o compartilhamento de shared.xaml que define um ResourceDictionary que contém um conjunto de recursos de estilo e de pincel que permite que os controles do exemplo tenham uma aparência consistente.

Para obter mais informações, consulte Dicionários de Recursos mesclados.

Se você estiver criando um tema para o seu controle personalizado, dê uma olhada na seção Biblioteca de Controles Externos de Visão geral sobre criação de controles.

Consulte também

Tarefas

Como: Localizar elementos ControlTemplate gerado

Como: Encontrar Elemento DataTemplate-Generated

Demonstração de armazenamento de fotos

Conceitos

URIs de Pacotes no Windows Presentation Foundation

Outros recursos

Temas