« Style » : différence entre les versions
Ligne 61 : | Ligne 61 : | ||
<Button Content="Button2"> | <Button Content="Button2"> | ||
<Button.Style> | <Button.Style> | ||
<Style TargetType="Button" BasedOn="{StaticResource | <Style TargetType="Button" BasedOn="{StaticResource Button}"> | ||
<Setter Property="Foreground" Value="Beige"/> | <Setter Property="Foreground" Value="Beige"/> | ||
</Style> | </Style> |
Version du 12 avril 2021 à 20:17
Définition
Permet de changer les valeurs des propriétés des objets graphiques.
Équivalent du CSS pour WPF.
Une fois appliqué, un style ne peut être modifié (propriété IsSealed). |
Syntaxe
Depuis les ressources
<Window.Resources> <!-- Style implicite (sans key), s'applique à toutes les types TextBox --> <Style TargetType="TextBox"> <Setter Property="Background" Value="Cyan" /> </Style> <!-- Change la propriété Background des TextBox qui utilisent explicitement ce style --> <Style x:Key="tbxStyle1" TargetType="TextBox"> <Setter Property="Background" Value="Red" /> </Style> </Window.Resources> <TextBox Style="{StaticResource tbxStyle1}"></TextBox> |
Directement dans le Control
<ComboBox SelectedIndex="0"> <ComboBox.Style> <Style TargetType="ComboBox"> <Setter Property="Background" Value="Cyan" /> </Style> </ComboBox.Style> </ComboBox> |
Héritage de style: BasedOn
Quand on définit le Style d'un Control, on écrase le Style précédemment définit:
<xxx.Resources> <!-- On définit un style par défaut qui va s'appliquer à tous les boutons --> <Style TargetType="Button"> <Setter Property="Background" Value="Cyan"/> </Style> </xxx.Resources> <!-- Ce bouton a bien son Background à Cyan --> <Button Content="Button1" /> <!-- Ici on redéfinit le style pour changer le Foreground --> <!-- Le style par défaut étant écrasé le Background est gris (style du système) --> <Button Content="Button2"> <Button.Style> <Style TargetType="Button" > <Setter Property="Foreground" Value="Beige"/> </Style> </Button.Style> </Button> |
La solution est d'hériter du Style par défaut:
<Button Content="Button2"> <Button.Style> <Style TargetType="Button" BasedOn="{StaticResource Button}"> <Setter Property="Foreground" Value="Beige"/> </Style> </Button.Style> </Button> |
BasedOn et DynamicResource
On utilise donc StaticResource pour hériter du style par défaut. Mais StaticResource contraint la ressource à se trouver définie dans le dictionnaire de ressources.
Ce n'est pas toujours le cas par exemple si une application définit son thème par défaut dans App.xaml et utilise des Control importés depuis d'autres assemblages. Ces Control n'auront pas d'accès "statique" au style par défaut, et l'héritage ne se fait pas.
La solution serait d'utiliser un lien "dynamique" mais BasedOn ne supporte pas DynamiqueResource.
Il faut donc créer son propre MarkupExtension:
[MarkupExtensionReturnType(typeof(object))] public class StaticApplicationResource : MarkupExtension { public StaticApplicationResource(object resourceKey) { ResourceKey = resourceKey; } [ConstructorArgument("resourceKey")] public object ResourceKey { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { if (ResourceKey == null) return null; // On cherche dans App.xaml (et pas ailleurs) si on trouve la ressource. return System.Windows.Application.Current.TryFindResource(ResourceKey); } } |
<Button Content="Button2"> <Button.Style> <Style TargetType="Button" BasedOn="{my:StaticApplicationResource {x:Type Button}}""> <Setter Property="Foreground" Value="Beige"/> </Style> </Button.Style> </Button> |
Ordre de résolution entre les Style
Valeur par défaut
public static readonly DependencyProperty MyValueProperty = DependencyProperty.Register("MyValue", typeof(string), typeof(MyCustomControl), new UIPropertyMetadata("Valeur par défaut")); |
Héritage
<Grid local:MyCustomControl.MyValue="Héritage"> <local:MyCustomControl /> </Grid> |
Style par défaut
<Style TargetType="{x:Type local:MyCustomControl}"> <Setter Property="MyValue" Value="Style par défaut" /> |
Style setters
<local:MyCustomControl> <local:MyCustomControl.Style> <Style TargetType="local:MyCustomControl"> <Setter Property="MyValue" Value="Style setters" /> |
Template triggers
<local:MyCustomControl> <local:MyCustomControl.Template> <ControlTemplate TargetType="local:MyCustomControl"> <ControlTemplate.Triggers> <Trigger Property="IsEnabled" Value="True"> <Setter Property="MyValue" Value="Template triggers" /> |
Style triggers
<local:MyCustomControl> <local:MyCustomControl.Style> <Style TargetType="local:MyCustomControl"> <Style.Triggers> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Visibility" Value="Collapsed" /> |
Style implicite
Dans un dictionnaire de ressources, style sans clé qui s'applique à tous les TargetType.
<!-- style sans clé qui s'applique à tous les TextBlock --> <Style TargetType="{x:Type TextBlock}"> <Setter Property="Foreground" Value="Blue" /> </Style> |
La clé est en fait le TargetType. |
TemplatedParent template properties
<ContentControl x:Name="contentControl"> <ContentControl.Template> <ControlTemplate TargetType="ContentControl"> <local:MyCustomControl MyValue="TemplatedParent template properties" x:Name="myCustomControl"> |
Valeur locale
myCustomControl.MyValue = "Valeur locale"; |