No WPF, como eu aplicaria vários estilos a um FrameworkElement
? Por exemplo, eu tenho um controle que já tem um estilo. Eu também tenho um estilo separado que eu gostaria de acrescentar a ele sem estragar o primeiro. Os estilos têm TargetTypes diferentes, então não posso apenas estender um com o outro.
153
Respostas:
Eu acho que a resposta simples é que você não pode fazer (pelo menos nesta versão do WPF) o que está tentando fazer.
Ou seja, para qualquer elemento específico, apenas um estilo pode ser aplicado.
No entanto, como outros já declararam acima, talvez você possa usar
BasedOn
para ajudá-lo. Confira o seguinte pedaço de xaml solto. Nele, você verá que eu tenho um estilo base que está definindo uma propriedade que existe na classe base do elemento ao qual desejo aplicar dois estilos. E, no segundo estilo, baseado no estilo base, defino outra propriedade.Portanto, a idéia aqui ... é que, de alguma forma, você pode separar as propriedades que deseja definir ... de acordo com a hierarquia de herança do elemento em que deseja definir vários estilos ... você pode ter uma solução alternativa.
Espero que isto ajude.
Nota:
Uma coisa em particular a ser observada. Se você alterar o
TargetType
segundo estilo (no primeiro conjunto de xaml acima) paraButtonBase
, os dois estilos não serão aplicados. No entanto, verifique o seguinte xaml abaixo para contornar essa restrição. Basicamente, isso significa que você precisa fornecer uma chave ao estilo e referenciá-lo com essa chave.fonte
derivedStyle
deve vir após obaseStyle
Bea Stollnitz teve um bom post sobre como usar uma extensão de marcação para isso, sob o título "Como posso definir vários estilos no WPF?"
Esse blog está morto agora, então estou reproduzindo o post aqui
O WPF e o Silverlight oferecem a capacidade de derivar um estilo de outro estilo por meio da propriedade “BasedOn”. Esse recurso permite que os desenvolvedores organizem seus estilos usando uma hierarquia semelhante à herança de classe. Considere os seguintes estilos:
Com essa sintaxe, um Button que usa RedButtonStyle terá sua propriedade Foreground definida como Red e sua propriedade Margin definida como 10.
Esse recurso existe no WPF há muito tempo e é novo no Silverlight 3.
E se você quiser definir mais de um estilo em um elemento? Nem o WPF nem o Silverlight fornecem uma solução para esse problema imediatamente. Felizmente, existem maneiras de implementar esse comportamento no WPF, que discutirei nesta postagem do blog.
O WPF e o Silverlight usam extensões de marcação para fornecer propriedades com valores que requerem alguma lógica para serem obtidos. As extensões de marcação são facilmente reconhecíveis pela presença de colchetes ao redor deles no XAML. Por exemplo, a extensão de marcação {Binding} contém lógica para buscar um valor de uma fonte de dados e atualizá-lo quando ocorrerem alterações; a extensão de marcação {StaticResource} contém lógica para obter um valor de um dicionário de recursos com base em uma chave. Felizmente para nós, o WPF permite que os usuários gravem suas próprias extensões de marcação personalizadas. Esse recurso ainda não está presente no Silverlight, portanto, a solução neste blog é aplicável apenas ao WPF.
Outros criaram ótimas soluções para mesclar dois estilos usando extensões de marcação. No entanto, eu queria uma solução que oferecesse a capacidade de mesclar um número ilimitado de estilos, o que é um pouco mais complicado.
Escrever uma extensão de marcação é simples. A primeira etapa é criar uma classe derivada de MarkupExtension e usar o atributo MarkupExtensionReturnType para indicar que você deseja que o valor retornado da extensão de marcação seja do tipo Style.
Especificando entradas para a extensão de marcação
Gostaríamos de oferecer aos usuários da nossa extensão de marcação uma maneira simples de especificar os estilos a serem mesclados. Existem basicamente duas maneiras pelas quais o usuário pode especificar entradas para uma extensão de marcação. O usuário pode definir propriedades ou passar parâmetros para o construtor. Como nesse cenário o usuário precisa especificar um número ilimitado de estilos, minha primeira abordagem foi criar um construtor que use qualquer número de strings usando a palavra-chave "params":
Meu objetivo era ser capaz de escrever as entradas da seguinte maneira:
Observe a vírgula separando as diferentes teclas de estilo. Infelizmente, as extensões de marcação personalizadas não oferecem suporte a um número ilimitado de parâmetros do construtor; portanto, essa abordagem resulta em um erro de compilação. Se eu soubesse com antecedência quantos estilos queria mesclar, poderia ter usado a mesma sintaxe XAML com um construtor que obtém o número desejado de strings:
Como solução alternativa, decidi fazer com que o parâmetro construtor usasse uma única sequência que especifique os nomes de estilos separados por espaços. A sintaxe não é tão ruim:
Calculando a saída da extensão de marcação
Para calcular a saída de uma extensão de marcação, precisamos substituir um método de MarkupExtension chamado "ProvideValue". O valor retornado desse método será definido no destino da extensão de marcação.
Comecei criando um método de extensão para o Style que sabe mesclar dois estilos. O código para este método é bastante simples:
Com a lógica acima, o primeiro estilo é modificado para incluir todas as informações do segundo. Se houver conflitos (por exemplo, ambos os estilos têm um setter para a mesma propriedade), o segundo estilo vence. Observe que, além de copiar estilos e gatilhos, também considerei os valores TargetType e BasedOn, bem como quaisquer recursos que o segundo estilo possa ter. Para o TargetType do estilo mesclado, usei o tipo que for mais derivado. Se o segundo estilo tiver um estilo BasedOn, mesclar sua hierarquia de estilos recursivamente. Se houver recursos, eu os copio para o primeiro estilo. Se esses recursos forem referidos como {StaticResource}, eles serão resolvidos estaticamente antes da execução desse código de mesclagem e, portanto, não será necessário movê-los. Eu adicionei esse código no caso de estarmos usando DynamicResources.
O método de extensão mostrado acima habilita a seguinte sintaxe:
Essa sintaxe é útil, desde que eu tenha instâncias de ambos os estilos no ProvideValue. Bem, eu não. Tudo o que recebo do construtor é uma lista de chaves de string para esses estilos. Se houvesse suporte para parâmetros nos parâmetros do construtor, eu poderia ter usado a seguinte sintaxe para obter as instâncias de estilo reais:
Mas isso não funciona. E mesmo que a limitação de parâmetros não existisse, provavelmente atingiríamos outra limitação de extensões de marcação, onde teríamos que usar a sintaxe de elemento de propriedade em vez da sintaxe de atributo para especificar os recursos estáticos, que são detalhados e pesados (eu explico isso bug melhor em uma postagem anterior do blog ). E mesmo que essas duas limitações não existissem, eu preferiria escrever a lista de estilos usando apenas seus nomes - é mais curto e mais simples de ler do que um StaticResource para cada um.
A solução é criar um StaticResourceExtension usando o código. Dada uma chave de estilo do tipo string e um provedor de serviços, posso usar StaticResourceExtension para recuperar a instância de estilo real. Aqui está a sintaxe:
Agora, temos todas as peças necessárias para escrever o método ProvideValue:
Aqui está um exemplo completo do uso da extensão de marcação MultiStyle:
fonte
Mas você pode estender de outro. Dê uma olhada na propriedade BasedOn
fonte
O WPF / XAML não fornece essa funcionalidade nativamente, mas fornece a extensibilidade para permitir que você faça o que deseja.
Tivemos a mesma necessidade e acabamos criando nossa própria extensão de marcação XAML (que chamamos de "MergedStylesExtension") para permitir a criação de um novo estilo a partir de dois outros estilos (que, se necessário, provavelmente poderiam ser usados várias vezes em um linha para herdar ainda mais estilos).
Devido a um bug do WPF / XAML, precisamos usar a sintaxe do elemento de propriedade para usá-lo, mas fora isso parece funcionar bem. Por exemplo,
Eu escrevi recentemente sobre isso aqui: http://swdeveloper.wordpress.com/2009/01/03/wpf-xaml-multiple-style-inheritance-and-markup-extensions/
fonte
Isso é possível criando uma classe auxiliar para usar e agrupar seus estilos. O CompoundStyle mencionado aqui mostra como fazê-lo. Existem várias maneiras, mas a mais fácil é fazer o seguinte:
Espero que ajude.
fonte
Use
AttachedProperty
para definir vários estilos, como o seguinte código:Usege:
Resultado:
fonte
se você não estiver tocando em nenhuma propriedade específica, poderá obter todas as propriedades básicas e comuns no estilo cujo tipo de destino seria FrameworkElement. então, você pode criar sabores específicos para cada tipo de destino necessário, sem precisar copiar todas essas propriedades comuns novamente.
fonte
Provavelmente, você pode obter algo semelhante ao aplicar isso a uma coleção de itens pelo uso de um StyleSelector, usei isso para abordar um problema semelhante ao usar estilos diferentes em TreeViewItems, dependendo do tipo de objeto vinculado na árvore. Pode ser necessário modificar a classe abaixo levemente para se ajustar à sua abordagem específica, mas espero que isso ajude você a começar
Você então aplica isso da seguinte maneira
fonte
Às vezes, você pode abordar isso aninhando painéis. Digamos que você tenha um estilo que muda o primeiro plano e outro o FontSize, você pode aplicar o último em um TextBlock e colocá-lo em uma grade cujo estilo é o primeiro. Isso pode ajudar e pode ser a maneira mais fácil em alguns casos, embora não resolva todos os problemas.
fonte
Quando você substitui o SelectStyle, pode obter a propriedade GroupBy através da reflexão, como abaixo:
fonte
Se você está tentando aplicar um estilo único a apenas um único elemento , além de um estilo base, há uma maneira completamente diferente de fazer isso: o IMHO é muito melhor para código legível e de manutenção.
É extremamente comum precisar ajustar parâmetros por elemento individual. Definir estilos de dicionário apenas para uso em um elemento é extremamente complicado de manter ou entender. Para evitar a criação de estilos apenas para ajustes pontuais de elementos, leia minha resposta para minha própria pergunta aqui aqui:
https://stackoverflow.com/a/54497665/1402498
fonte