Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF default styles and UserControls - Best practices?

Tags:

.net

styles

wpf

I have the following situation (simplified):

In my ResourceDictionary, I have defined a couple of named styles for Label:

<Style
    x:Key="sNormalLabel"
    TargetType="Label" >
    <Setter Property="FontFamily" Value="Verdana" />
    <Setter Property="FontSize" Value="12" />
    <!-- ... -->
</Style>
<Style
    x:Key="sHeaderLabel"
    TargetType="Label"
    BasedOn="{StaticResource sNormalLabel}" >
    <Setter Property="FontSize" Value="16" />
</Style>

And then I make one of them default by referencing it with BasedOn, in a style that doesn't have a key:

<!-- Apply Normal label automatically -->
<Style 
    TargetType="Label"
    BasedOn="{StaticResource sNormalLabel}" />

I thought it very convenient to apply the normal style of label automatically, that way I know that if in the future our design team decides to go with Wingdings or something, it is very easy to change for the entire application (in fact all applications that share the same ResourceDictionary).

Creating a UserControl I want to add a Label at the top with the sHeaderLabel style, so as it goes I apply

Style={StaticResource sHeaderLabel}

in the USerControl XAML, and all looks fine in the designer.

However, when I add the UserControl to the MainWindow, the header label goes back to the sNormalLabel style (the automatically applied one).

I assume it has to do with the order in which the styles are applied, the UserControl is styled by the MainWindow after it is created, and the sHeaderLabel style is overwritten by the automatic one.

This leaves me with a couple of unanswered questions:

  1. Is it uncommon and contrary to best-practice to use automatically applied styles as I have done? I thought it very practical, but maybe this is the wrong way to go.
  2. Is there any way to exclude certain controls explicitly from having these automatic styles applied? The only way I can think of is to extend Label with HeaderLabel and apply a different resource key, so that HeaderLabel automatically has sHeaderLabel style applied to it. Is there any other way?

If anyone has any practical experience with something similar, I would appreciate some pointers.

EDIT: Interestingly, I just realized that I only see these problems with the Font* properties. Setting Foreground/Background brushes differently in Normal/Header style leaves the Label in the UserControl (which is styled to sHeaderLabel) with the CORRECT color. Setting FontWeight to bold in sHeaderLabel has no effect however.

I have also set up TextBox styles in the same way, with a HeaderTExtBox style, and I don't see the problem there either, only with Labels.

Cheers!

./Fredrik

like image 802
Fredrik Avatar asked Nov 02 '22 17:11

Fredrik


1 Answers

A good practice may be to avoid applying base automatic styles to standard types, since the results can be unpredictable.

In response to what ended up being your issue, a good example is applying a style to TextBlock. This style is going to be applied to Label, Button, and any other control anywhere in the framework that may contain a TextBlock that isn't overriding the style you're setting.

You can't "un-apply" a style when applying them to all instances of a type, you can only override the style with a new style. Unless you can accurately predict everything in your application that this will effect (such as styling a control you made), you should avoid using the automatic style in favor of setting the x:Key.

like image 157
Will Eddins Avatar answered Jan 04 '23 15:01

Will Eddins