Compartilhar via


Modelos de controle

Você pode personalizar a estrutura visual e o comportamento visual de um controle criando um modelo de controle na estrutura XAML. Os controles têm muitas propriedades, como Background, Foreground e FontFamily, que você pode definir para especificar diferentes aspectos da aparência do controle. Mas as alterações que você pode fazer definindo essas propriedades são limitadas. Você pode especificar personalizações adicionais criando um modelo usando a classe ControlTemplate . Aqui, mostramos como criar um ControlTemplate para personalizar a aparência de um controle CheckBox.

APIs importantes: classe ControlTemplate, propriedade Control.Template

Exemplo de modelo de controle personalizado

Por padrão, um controle CheckBox coloca seu conteúdo (a cadeia de caracteres ou objeto ao lado do CheckBox) à direita da caixa de seleção e uma marca de seleção indica que um usuário selecionou o CheckBox. Essas características representam a estrutura visual e o comportamento visual do CheckBox.

Aqui está uma CheckBox usando o ControlTemplate padrão mostrado nos Uncheckedestados , Checkede .Indeterminate

Modelo de caixa de seleção padrão

Você pode alterar essas características criando um ControlTemplate para o CheckBox. Por exemplo, se você quiser que o conteúdo da caixa de seleção esteja abaixo da caixa de seleção e quiser usar um X para indicar que um usuário marcou a caixa de seleção. Você especifica essas características no ControlTemplate do CheckBox.

Para usar um modelo personalizado com um controle, atribua o ControlTemplate à propriedade Template do controle. Aqui está um CheckBox usando um ControlTemplate chamado CheckBoxTemplate1. Mostramos a XAML (Extensible Application Markup Language) para o ControlTemplate na próxima seção.

<CheckBox Content="CheckBox" Template="{StaticResource CheckBoxTemplate1}" IsThreeState="True" Margin="20"/>

Veja como essa CheckBox aparece no Unchecked, Checkede Indeterminate estados depois de aplicarmos nosso modelo.

Modelo de caixa de seleção personalizado

Especificar a estrutura visual de um controle

Ao criar um ControlTemplate, você combina objetos FrameworkElement para criar um único controle. Um ControlTemplate deve ter apenas um FrameworkElement como seu elemento raiz. O elemento raiz geralmente contém outros objetos FrameworkElement . A combinação de objetos compõe a estrutura visual do controle.

Esse XAML cria um ControlTemplate para um CheckBox que especifica que o conteúdo do controle está abaixo da caixa de seleção. O elemento raiz é um Border. O exemplo especifica um Path para criar um X que indica que um usuário selecionou o CheckBox e uma Ellipse que indica um estado indeterminado. Observe que a Opacidade é definida como 0 no Caminho e na Elipse para que, por padrão, nenhum deles apareça.

Um TemplateBinding é uma associação especial que vincula o valor de uma propriedade em um modelo de controle ao valor de outra propriedade exposta no controle de modelo. TemplateBinding só pode ser usado em uma definição de ControlTemplate em XAML. Confira Extensão de marcação TemplateBinding para obter mais informações.

Observação

Começando com o Windows 10, versão 1809 (SDK 17763), você pode usar extensões da marcação x:Bind em lugares em que usa TemplateBinding. Confira Extensão de marcação TemplateBinding para obter mais informações.

<ControlTemplate x:Key="CheckBoxTemplate1" TargetType="CheckBox">
    <Border BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="{TemplateBinding Background}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>
            <Rectangle x:Name="NormalRectangle" Fill="Transparent" Height="20" Width="20"
                       Stroke="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
                       StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}"
                       UseLayoutRounding="False"/>
            <!-- Create an X to indicate that the CheckBox is selected. -->
            <Path x:Name="CheckGlyph"
                  Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z"
                  Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                  FlowDirection="LeftToRight"
                  Height="14" Width="16" Opacity="0" Stretch="Fill"/>
            <Ellipse x:Name="IndeterminateGlyph"
                     Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                     Height="8" Width="8" Opacity="0" UseLayoutRounding="False" />
            <ContentPresenter x:Name="ContentPresenter"
                              ContentTemplate="{TemplateBinding ContentTemplate}"
                              Content="{TemplateBinding Content}"
                              Margin="{TemplateBinding Padding}" Grid.Row="1"
                              HorizontalAlignment="Center"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
    </Border>
</ControlTemplate>

Especificar o comportamento visual de um controle

Um comportamento visual especifica a aparência de um controle quando ele está em um determinado estado. O controle CheckBox tem 3 estados de verificação: Checked, Uncheckede Indeterminate. O valor da propriedade IsChecked determina o estado da CheckBox e seu estado determina o que aparece na caixa.

Esta tabela lista os valores possíveis de IsChecked, os estados correspondentes do CheckBox e a aparência do CheckBox.

Valor IsChecked Estado CheckBox Aparência da caixa de seleção
true Checked Contém um "X".
false Unchecked Vazio.
nulo Indeterminate Contém um círculo.

Você especifica a aparência de um controle quando ele está em um determinado estado usando objetos VisualState . Um VisualState contém um Setter ou Storyboard que altera a aparência dos elementos no ControlTemplate. Quando o controle entra no estado especificado pela propriedade VisualState.Name, as alterações de propriedade no Setter ou no Storyboard são aplicadas. Quando o controle sai do estado, as alterações são removidas. Você adiciona objetos VisualState a objetos VisualStateGroup . Você adiciona objetos VisualStateGroup à propriedade anexada VisualStateManager.VisualStateGroups, que você define na raiz FrameworkElement do ControlTemplate.

Esse XAML mostra os objetos VisualState para os Checkedestados , Uncheckede .Indeterminate O exemplo define a propriedade anexada VisualStateManager.VisualStateGroups na Borda, que é o elemento raiz do ControlTemplate. O Checked VisualState especifica que a Opacity do Path chamado CheckGlyph (que mostramos no exemplo anterior) é 1. O Indeterminate VisualState especifica que a Opacity da Ellipse chamada IndeterminateGlyph é 1. O Unchecked VisualState não tem nenhum Setter ou Storyboard e, portanto, a CheckBox volta à aparência padrão.

<ControlTemplate x:Key="CheckBoxTemplate1" TargetType="CheckBox">
    <Border BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="{TemplateBinding Background}">

        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CheckStates">
                <VisualState x:Name="Checked">
                    <VisualState.Setters>
                        <Setter Target="CheckGlyph.Opacity" Value="1"/>
                    </VisualState.Setters>
                    <!-- This Storyboard is equivalent to the Setter. -->
                    <!--<Storyboard>
                        <DoubleAnimation Duration="0" To="1"
                         Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Opacity"/>
                    </Storyboard>-->
                </VisualState>
                <VisualState x:Name="Unchecked"/>
                <VisualState x:Name="Indeterminate">
                    <VisualState.Setters>
                        <Setter Target="IndeterminateGlyph.Opacity" Value="1"/>
                    </VisualState.Setters>
                    <!-- This Storyboard is equivalent to the Setter. -->
                    <!--<Storyboard>
                        <DoubleAnimation Duration="0" To="1"
                         Storyboard.TargetName="IndeterminateGlyph" Storyboard.TargetProperty="Opacity"/>
                    </Storyboard>-->
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>
            <Rectangle x:Name="NormalRectangle" Fill="Transparent" Height="20" Width="20"
                       Stroke="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
                       StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}"
                       UseLayoutRounding="False"/>
            <!-- Create an X to indicate that the CheckBox is selected. -->
            <Path x:Name="CheckGlyph"
                  Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z"
                  Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                  FlowDirection="LeftToRight"
                  Height="14" Width="16" Opacity="0" Stretch="Fill"/>
            <Ellipse x:Name="IndeterminateGlyph"
                     Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                     Height="8" Width="8" Opacity="0" UseLayoutRounding="False" />
            <ContentPresenter x:Name="ContentPresenter"
                              ContentTemplate="{TemplateBinding ContentTemplate}"
                              Content="{TemplateBinding Content}"
                              Margin="{TemplateBinding Padding}" Grid.Row="1"
                              HorizontalAlignment="Center"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
    </Border>
</ControlTemplate>

Para entender melhor como os objetos VisualState funcionam, considere o que acontece quando o CheckBox vai do Unchecked estado para o Checked estado, depois para o Indeterminate estado e, em seguida, de volta para o Unchecked estado. Aqui estão as transições.

Transição de estado O que acontece Aparência da caixa de seleção quando a transição for concluída
De Unchecked para Checked. O valor Setter do Checked VisualState é aplicado e, portanto, a Opacity de CheckGlyph é 1. Um X é exibido.
De Checked para Indeterminate. O valor Setter do Indeterminate VisualState é aplicado e, portanto, a Opacity de IndeterminateGlyph é 1. O valor Setter do Checked VisualState é removido e, portanto, a Opacity de CheckGlyph é 0. Um círculo é exibido.
De Indeterminate para Unchecked. O valor Setter do Indeterminate VisualState é removido e, portanto, a Opacity de IndeterminateGlyph é 0. Nada é exibido.

  Para obter mais informações sobre como criar estados visuais para controles e, em particular, como usar a classe Storyboard e os tipos de animação, consulte Animações com storyboard para estados visuais.

Use ferramentas para trabalhar com temas facilmente

Uma maneira rápida de aplicar temas aos seus controles é clicar com o botão direito do mouse em um controle na Estrutura de Tópicos do Documento do Microsoft Visual Studio e selecionar Editar Tema ou Editar Estilo (dependendo do controle em que você está clicando com o botão direito do mouse). Em seguida, você pode aplicar um tema existente selecionando Aplicar Recurso ou definir um novo selecionando Criar Vazio.

Controles e acessibilidade

Quando você cria um novo modelo para um controle, além de possivelmente alterar o comportamento e a aparência visual do controle, você também pode estar alterando a forma como o controle se representa para estruturas de acessibilidade. O aplicativo do Windows é compatível com a estrutura de Automação da Interface do Usuário da Microsoft para acessibilidade. Todos os controles padrão e seus modelos têm suporte para tipos e padrões comuns de controle de Automação da Interface do Usuário apropriados para a finalidade e a função do controle. Esses tipos e padrões de controle são interpretados por clientes de automação da interface do usuário, como tecnologias adaptativas, e isso permite que um controle seja acessível como parte de uma interface do usuário de aplicativo acessível maior.

Para separar a lógica de controle básica e também para atender a alguns dos requisitos de arquitetura de Automação da Interface do Usuário, as classes de controle incluem seu suporte de acessibilidade em uma classe separada, um par de automação. Os pares de automação às vezes têm interações com os modelos de controle porque os pares esperam que determinadas partes nomeadas existam nos modelos, de modo que a funcionalidade, como habilitar tecnologias assistivas para invocar ações de botões, seja possível.

Quando você cria um controle personalizado completamente novo, às vezes você também desejará criar um novo par de automação para acompanhá-lo. Para obter mais informações, consulte Pares de automação personalizados.

Saiba mais sobre o modelo padrão de um controle

Os tópicos que documentam os estilos e modelos para controles XAML mostram trechos do mesmo XAML inicial que você veria se usasse as técnicas Editar Tema ou Editar Estilo explicadas anteriormente. Cada tópico lista os nomes dos estados visuais, os recursos de tema usados e o XAML completo para o estilo que contém o modelo. Os tópicos podem ser diretrizes úteis se você já tiver começado a modificar um modelo e quiser ver a aparência do modelo original ou verificar se o novo modelo tem todos os estados visuais nomeados necessários.

Recursos de tema em modelos de controle

Para alguns dos atributos nos exemplos XAML, você deve ter notado referências de recursos que usam a extensão de marcação {ThemeResource}. Essa é uma técnica que permite que um único modelo de controle use recursos que podem ter valores diferentes, dependendo de qual tema está ativo no momento. Isso é particularmente importante para pincéis e cores, pois o principal objetivo dos temas é permitir que os usuários escolham se desejam um tema escuro, claro ou de alto contraste aplicado ao sistema em geral. Os aplicativos que usam o sistema de recursos XAML podem usar um conjunto de recursos apropriado para esse tema, de modo que as opções de tema na interface do usuário de um aplicativo reflitam a escolha de tema em todo o sistema do usuário.

Obter o código de exemplo