Modelos de controle

Você pode personalizar a estrutura 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 mudanças que você pode fazer ao definir essas propriedades são limitadas. Você pode especificar personalizações adicionais criando um modelo usando a classe ControlTemplate. Aqui, mostramos a você como criar um ControlTemplate para personalizar a aparência de um controle CheckBox.

APIs importantes: classe ControlTemplate, propriedade Control.Template

Amostra de modelo de controle personalizado

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

Consulte um CheckBox usando o ControlTemplate padrão mostrado nos estados Unchecked, Checked e Indeterminate.

modelo de caixa de seleção padrão

Você pode mudar estas características criando um ControlTemplate para CheckBox. Por exemplo, se você quiser que o conteúdo da caixa de seleção fique 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 estas características no ControlTemplate de CheckBox.

Para usar um modelo personalizado com um controle, você atribui o ControlTemplate à propriedade Template do controle. Aqui está uma CheckBox usando um ControlTemplate chamado CheckBoxTemplate1. Mostramos a linguagem XAML para o ControlTemplate na próxima seção.

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

Consulte como este CheckBox fica nos estados Unchecked, Checked, e Indeterminate após aplicarmos o nosso modelo.

modelo personalizado de caixa de seleção

Especificar a estrutura visual de um controle

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

Este XAML cria um ControlTemplate para um CheckBox que especifica que o conteúdo do controle está abaixo da caixa de seleção. O elemento da raiz é um Border. O exemplo especifica um Path para criar um X que indica que um usuário selecionou o CheckBox e um Ellipse que indica um estado indeterminado. Note que o Opacity está definido como 0 no Path e Ellipse de forma que por padrão, nenhum aparece.

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 dentro de uma definição 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 do controle

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

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

Valor IsChecked Estado da CheckBox Aparência da CheckBox
true Checked Contém um "X".
false Unchecked Vazio.
null Indeterminate Contém um círculo.

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

Este XAML mostra os objetos VisualState para os estados Checked, Unchecked e Indeterminate. O exemplo define a propriedade VisualStateManager.VisualStateGroups anexada no Border, que é o elemento raiz do ControlTemplate. O CheckedVisualState especifica que a Opacidade do Caminho chamado CheckGlyph (que mostramos no exemplo anterior) é 1. O IndeterminateVisualState especifica que a opacidade da elipse chamada IndeterminateGlyph é 1. O UncheckedVisualState não tem Setter ou Storyboard, portanto, a CheckBox retorna à sua 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 ocorre quando CheckBox vai do estado Unchecked ao estado Checked e, em seguida, ao estado Indeterminate e, em seguida, de volta ao estado Unchecked. Estes são as transições:

Transição de estado O que ocorre Aparência da caixa de seleção quando a transição completa
De Unchecked a Checked. O valor Setter do CheckedVisualState é aplicado, portanto, a opacidade de CheckGlyph é 1. Um X é exibido.
De Checked a Indeterminate. O valor Setter do IndeterminateVisualState é aplicado, portanto, a opacidade de IndeterminateGlyph é 1. O valor Setter do CheckedVisualState é removido, portanto, a opacidade de CheckGlyph é 0. Um círculo é exibido.
De Indeterminate a Unchecked. O valor Setter do IndeterminateVisualState é removido, portanto, a opacidade de IndeterminateGlyph é 0. Nada é exibido.

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

Use as ferramentas para trabalhar com os temas facilmente

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

Controles e acessibilidade

Ao criar um novo modelo de controle, além da possibilidade de mudar o comportamento e a aparência visual do controle, você também pode alterar como o controle se representa nas 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 permitem tipos e padrões comuns de controle de Automação da Interface do Usuário adequados 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, permitindo acessar um controle 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 atender a alguns requisitos de arquitetura da Automação da Interface do Usuário, as classes de controle incluem o suporte para 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, pois os pares esperam que existam determinadas partes nomeadas nos modelos para que funcionalidades, como a habilitação de tecnologias adaptativas, possam invocar as ações dos botões.

Ao criar um controle personalizado completamente novo, convém também criar um novo par de automação para trabalhar com ele. 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 dos controles de 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 temas usados e o XAML completo para o estilo que contém o modelo. Os tópicos podem ser diretrizes úteis se você já começou a modificar um modelo e quer ver qual era a aparência do modelo original ou verificar se o novo modelo tem todos os estados visuais nomeados obrigatórios.

Recursos de tema em modelos de controle

Para alguns dos atributos nos exemplos de XAML, você pode ter percebido 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 ser valores diferentes dependendo de qual tema está ativo no momento. Isso é particularmente importante para pincéis e cores, porque a finalidade principal dos temas é permitir que os usuários escolham se querem um tema de contraste escuro, claro ou alto aplicado ao sistema como um todo. Os aplicativos que usam o sistema de recursos de XAML podem usar um conjunto de recursos apropriado para esse tema, de maneira que as escolhas de tema na interface do usuário de um aplicativo reflitam a escolha de tema em todo o sistema feita pelo usuário.

Obter o código de exemplo