Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
Suppose I have a WPF style for a container element such as a grid which applies styles to its child items automatically, like this:
<Window.Resources>
<Style TargetType="Grid" x:Key="FormStyle">
<Style.Resources>
<Style TargetType="Label">
<Setter Property="FontSize" Value="50"/>
</Style>
</Style.Resources>
</Style>
</Window.Resources>
How can I then override certian elements of that style within the grid itself? For example suppose I wanted one grid to have FormStyle but also have a blue label, like this (which doesnt work):
<!-- this works fine and Label size = 50 -->
<Grid Style="{StaticResource FormStyle}">
<Label Content="Blah"/>
</Grid>
<!-- But this doesnt, label is blue, but normal font size -->
<Grid Style="{StaticResource FormStyle}">
<Grid.Resources>
<Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="Foreground" Value="Blue"/>
</Style>
</Grid.Resources>
<Label Content="Blah"/>
</Grid>
I am expecting the BasedOn={StaticResource {x:Type Label}}
to refer to the current active style for Labels at the current scope - i.e. the label style within FormStyle. But it clearly doesnt and refers to the base outer label style.
If I do for instance this globally
<Style TargetType="Label">
<Setter Property="FontSize" Value="50"/>
</Style>
Then it is all fine.
I could of course just name the styles, but surly there must be an easier/less verbose way?
Thanks
The lookup process checks for the requested key within the resource
dictionary defined by the element that sets the property.
The lookup process then traverses the logical tree upward to the
parent element and its resource dictionary. This process continues
until the root element is reached.
App resources are checked. App resources are those resources within
the resource dictionary that is defined by the Application object
for your WPF app.
In your case to resolve BasedOn="{StaticResource {x:Type Label}}"
WPF first looks in the ResourceDictionary
defined inside of Grid
, then in Window
- the logical parent of the Grid - and it's Resources
, and then finally in Application level resources. WPF will not find it anywhere - and defaults to the base style - due to the style being a nested style in FormStyle
.
Read further about Static Resource Lookup Behavior on Docs.
To get the desired output, you could:
1) Move your Label
style out of FormStyle
and in to Window.Resoruces
2) Merge the Label style from FormStyle
into the Label style defined in the Grid
element.
<Grid Style="{StaticResource FormStyle}">
<Grid.Resources>
<Style TargetType="Label">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="FontSize" Value="50"/>
</Style>
</Grid.Resources>
<Label Content="Blah"/>
</Grid>
3) Change your FormStyle
not to have a nested style for Label
, but to have setters for Label properties.
<Window.Resources>
<Style TargetType="Grid" x:Key="FormStyle">
<Setter Property="Label.FontSize" Value="50"/>
</Style>
</Window.Resources>
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.