Diretrizes para criação de controles estilizados
Esse documento resume um conjunto de práticas recomendadas para considerar ao criar um controle que você pretende que seja facilmente estilizável e modelável. Nós chegamos a este conjunto de práticas recomendadas através de muita tentativa e erro enquanto trabalhamos nos estilos de controle tema para o conjunto de controles interno do WPF . Aprendemos que estilização bem-sucedida é função de um modelo de objeto bem desenhado assim como o próprio estilo. O público-alvo deste documento são os autores de controle, não os autores de estilo.
Este tópico contém as seguintes seções.
- Terminologia
- Antes de iniciar: Noções básicas sobre o controle
- Diretrizes gerais
- Considerações de tema
- Tópicos relacionados
Terminologia
"Estilização e modelação" referem-se ao conjunto de tecnologias que permitem um autor de controle adiar os aspectos visuais do controle para o estilo e modelo do controle. Este conjunto de tecnologias inclui:
Os estilos (incluindo setters, disparadores e storyboards).
Recursos:
Modelos de controle
Modelos de dados.
Para obter uma introdução aos estilos e modelagem, consulte Styling and Templating.
Antes de iniciar: Noções básicas sobre o controle
Antes que pular nessas diretrizes, é importante compreender e definir o uso comum do seu controle. Estilo expõe um conjunto geralmente irregular de possibilidades. Os controles criados para serem usados amplamente (em vários aplicativos, por vários desenvolvedores) enfrentam o desafio que estilos podem ser usado para fazer alterações grandes na aparência visual do controle. Na verdade, o controle estilizado pode nem mesmo lembrar as intenção do autor do controle. Como a flexibilidade oferecida pelo estilo é essencialmente sem-limites, você pode usar o conceito de uso comum para ajudar você a formular o escopo de suas decisões.
Para entender o uso comum de seu controle, é bom pensar sobre a valor da proposta do controle. O que faz seu controle que nenhum outro controle pode oferecer? Uso comum não implica nenhum aparência visual específica, mas em vez disso, a filosofia do controle e um conjunto razoável de expectativas sobre seu uso. Essa compreensão permite que você faça algumas suposições sobre o modelo de composição e os comportamentos definidos pelo estilo do controle no caso comum. No caso de ComboBox, por exemplo, noções básicas sobre o uso comum não dará qualquer esclarecimento sobre se um determinado ComboBox foi arredondado cantos, mas ele fornecerá informações sobre o fato que o ComboBox provavelmente precisa uma janela pop-up e alguma forma de alternância se ele é aberto.
Diretrizes gerais
Não estritamente se aplica a contratos de modelos. O modelo do contrato de um controle pode consistir de elementos, comandos, ligações, disparadores ou mesmo configurações de propriedade que são necessárias ou esperadas para um controle para funcionar corretamente.
Minimize contratos tanto quanto possível.
Design em torno de expectativa de que durante a criação do time (ou seja, ao usar uma ferramenta de design) é comum para um modelo de controle em um estado incompleto. WPFnão oferece uma infra-estrutura de estado "composing", para que controles precisam ser montado com a expectativa de que tal um estado pode ser válido.
Não lance exceções quando qualquer aspecto de um modelo de contrato não é seguido. Além dessas linhas, painéis não devem lançar exceções se tiverem muitos ou poucos filhos.
Fatore funcionalidades periféricas em elementos auxiliares de modelo. Cada controle deve ser concentra-se em suas funcionalidade principais e valores de proposta verdadeiros e definido pelo uso comum do controle. Ao final, use elementos de composição e auxílio dentro de modelo para habilitar comportamentos e visualizações periféricos, isto é, os comportamentos e visualizações que não contribuem para a funcionalidade central do Controle. Elementos auxiliares se enquadram em três categorias:
Tipos auxiliares autônomos são controles públicos e reutilizáveis ou primitivos que são usados "anonimamente" em um modelo, o que significa que nem o elemento auxiliar e nem o controle estilizado está ciente do outro. Tecnicamente, qualquer elemento pode ser um tipo anônimo, mas nesse contexto o termo descreve os tipos que encapsulam funcionalidades especializadas para habilitar cenários de destino.
Elementos auxiliartipo base são novos tipos que encapsulam funcionalidades especializadas. Esses elementos são normalmente criados com um intervalo mais estreito de funcionalidade de controles comuns ou primitivos. Diferentemente dos elementos auxiliares autônomo, elementos auxiliares de tipo com são cientes do contexto no qual eles são usados e geralmente devem compartilhar dados com o controle ao modelo que eles pertencem.
Elementos auxiliares nomeados são controles comuns ou primitivos que um controle espera localizá-lo em seu modelo pelo nome. Esses elementos recebem um nome conhecido dentro do modelo, tornando possível para um controle para localizar o elemento e interagir com ele por meio de programação. Pode haver apenas um elemento com um determinado nome em qualquer modelo.
A tabela a seguir mostra elementos auxiliar empregados pelo controle estilos hoje (essa lista não é completa):
Elemento
Type (Tipo)
Usado por
Com base no tipo
Button, CheckBox, RadioButton, Frame, e assim por diante (todos os tipos ContentControl)
Com base no tipo
ListBox, ComboBox, Menu, e assim por diante (todos os tipos ItemsControl)
Com nome
Standalone
Com nome
Com nome
Standalone
Standalone
Com nome
Com base no tipo
Minimize ligações especificadas pelo usuário ou configurações de propriedade necessárias nos elementos auxiliares . É comum um elemento auxiliar exigir determinadas ligações ou configurações de propriedade para funcionar corretamente no modelo do controle. O elemento auxiliar e controle modelo devem, o quanto possível, estabelecer essas configurações. Ao definir propriedades ou estabelecer as ligações, tome cuidado para não substituir valores definidos pelo usuário. Práticas recomendadas são:
Elementos auxiliar nomeado devem ser identificados pelo pai e o pai deve estabelecer qualquer configuração necessária no elemento auxiliar.
Elementos auxiliares baseados no tipo devem estabelecer as configurações necessárias diretamente em si. Isso pode exigir que o elemento auxiliar consulte informações de contexto no qual ele está sendo usado, incluindo suas TemplatedParent (o tipo de controle do modelo no qual ele está sendo usado). Por exemplo, ContentPresenter vincula automaticamente a propriedade Content de seus TemplatedParent para sua propriedade Content quando usado em um tipo derivado de ContentControl.
Elementos auxiliares autônomos não podem ser otimizados dessa maneira porque, por definição, nem o elemento auxiliar nem o pai sabem sobre o outro.
Use a propriedade Name para sinalizar elementos em um modelo . Um controle que precisa localizar um elemento no seu estilo para acessá-lo por meio de programação deve fazer isso usando a propriedade Name e o paradigma FindName. Um controle não deve gerar uma exceção quando um elemento não for encontrado, mas desabilitar silenciosamente a funcionalidade que requisitou aquele elemento.
**Use as práticas recomendadas para expressar o estado do controle e o comportamento em um estilo.**A seguir é uma lista ordenada de práticas recomendadas para expressar alterações de estado de controle e o comportamento em um estilo. Você deve usar o primeiro item na lista que permite a sua situação.
Associação de Propriedade. Exemplo: ligação entre ComboBox.IsDropDownOpen e ToggleButton.IsChecked.
Alterações de propriedade acionadas ou animações de propriedade. Exemplo: o estado focalizar de um Button.
Comando. Exemplo: LineUpCommand / LineDownCommand em ScrollBar.
Elementos auxiliares autônomos. Exemplo: TabPanel em TabControl.
Tipos auxiliares baseados no tipo. Exemplo: ContentPresenter em Button, TickBar em Slider.
Elementos auxiliares com nome. Exemplo: TextBox em ComboBox.
Eventos borbulhados de tipos auxiliares com nome. Se você escutar eventos borbulhados de um elemento de estilo, você deve exigir que o elemento que gera o evento possa ser identificado com exclusividade. Exemplo: Thumb em ToolBar.
Comportamento OnRender personalizado. Exemplo: ButtonChrome em Button.
Usar disparadores de estilo (em vez de disparadores de modelo) com moderação . Disparadores que afetam as propriedades em elementos de modelo devem ser declarados no modelo. Disparadores que afetam propriedades do controle (não TargetName) podem ser declaradas no estilo, a menos que você saiba que alterar o modelo deve também destruir o disparador.
Ser consistente com padrões de estilos existentes. Muitas vezes existem várias maneiras de solucionar um problema. Esteja ciente e, quando possível, consistente com padrões existentes de estilos de controle. Isso é especialmente importante para os controles que derivam do mesmo tipo base (por exemplo, ContentControl, ItemsControl, RangeBase, e assim por diante).
Expor as propriedades para habilitar situações comuns de personalização sem retemplating. WPF não suporte partes conectável/personalizáveis, para que um controle de usuário for deixado com apenas dois métodos de personalização: Definindo propriedades diretamente ou definindo as propriedades de uso de estilos. Com isso em mente, isto é apropriado para um número limitado de propriedades direcionadas a cenários de personalização muito comuns e de alta prioridade que exigem caso contrário, o remodelamento. Aqui estão as práticas recomendadas para quando e como habilitar cenários de personalização:
Personalizações muito comuns devem ser expostas como propriedades do controle e consumidas pelo modelo.
Personalizações menos comuns (embora não raras) devem ser expostas como propriedades anexadas e consumidas pelo modelo.
É aceitável para personalizações conhecidas mas raro exigir remodelagem.
Considerações de tema
Estilos de temas devem tentar ter semântica de propriedade consistente entre todos os temas, mas nenhuma garantia. Como parte de sua documentação, o controle deve ter um documento que descreve as semânticas de propriedade do controle, ou seja, o "significado" de uma propriedade para um controle. Por exemplo, o controle ComboBox deve definir o significado da propriedade Background no ComboBox. Os estilos padrões para o controle devem tentar seguir as semânticas definidas nesse documento para todos os temas. Os usuários de controle, por outro lado, devem estar cientes que a semântica de propriedade pode mudar de tema para tema. Em alguns casos, uma determinada propriedade pode não ser expressável sob as restrições visuais exigidas por um tema específico. (O tema clássico, por exemplo, não tem uma única borda para que o Thickness possa ser aplicado para vários controles.)
Estilos de tema não precisam ter a semântica de disparador consistente para todos os temas . O comportamento exposto por um estilo de controle por meio de disparadores ou animações pode variar de tema para tema. Os usuários do controle devem estar cientes que um controle não irá necessariamente empregar o mesmo mecanismo para atingir um determinado comportamento em todos os temas. Um tema, por exemplo, pode usar uma animação para expressar o comportamento de foco enquanto outro tema usa um disparador. Isso pode resultar em inconsistências na preservação do comportamento em controles personalizados. (Alterar a propriedade de plano de fundo, por exemplo, talvez não afete o estado de foco do controle se esse estado é expresso com um disparador. No entanto, se o estado de foco é implementado usando uma animação, alterar para o plano de fundo foi interromper irremediavelmente a animação e, portanto, a transição de estado.)
Estilos de tema não precisam ter a semântica de disparador de "layout" consistente para todos os temas . Por exemplo, o estilo padrão não precisa garantir que um controle irá ocupar a mesma quantidade de tamanho em todos os temas ou garantir que um controle terá as mesmas margens de conteúdo / preenchimento em todos os temas.