« Style » : différence entre les versions
Ligne 47 : | Ligne 47 : | ||
</Style> | </Style> | ||
</xxx.Resources> | </xxx.Resources> | ||
</kode> | |||
== BasedOn et DynamicResource == | == BasedOn et DynamicResource == |
Dernière version du 19 octobre 2021 à 21:28
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
BasedOn permet d'hériter d'un autre style afin de l'enrichir.
<xxx.Resources> <!-- On hérite du style par défaut des boutons --> <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}"> <Setter Property="Background" Value="Blue" /> </Style> <!-- On hérite du style CustomButtonStyle --> <Style TargetType="Button" BasedOn="{StaticResource CustomButtonStyle}"> <Setter Property="Background" Value="Blue" /> </Style> </xxx.Resources> |
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"; |