wpf
wpf copied to clipboard
Implicit style lookup not working correctly when control is part of a template
Description
Implicit style lookup not working correctly when control is part of a template.
That's because FindImplicitStyleResource sets a boundaryElement which causes implicit style lookup to bubble up to the ContentPresenter and immediately skip to App- and Theme-Resources.
There is a comment in the code stating:
// For non-controls the implicit StyleResource lookup must stop at // the templated parent. Look at task 25606 for further details.
I have no clue what's inside task 25606, but if that code there is really required the details should be added to the comment.
Reproduction Steps
See repro StyleLookup.zip
Expected behavior
Both TextBlock elements should have a green foreground.
Actual behavior
The TextBlock generated by the ContentPresenter has a red foreground. Regular TextBlock has a green foreground.
Regression?
No
Known Workarounds
A workaround will be shown in the commits fixing https://github.com/snoopwpf/snoopwpf/issues/397 But such workaround is not suitable for regular applications i think.
Impact
No response
Configuration
No response
Other information
No response
@batzen I think this is a WPF bug. But as you says, we do not know the task 25606, and maybe this behavior is to fix another bug.
I always thought this was by design, since the ad-hoc TextBlock created by the ContentPresenter has no real connection to the surrounding MainWindow.
Likewise the text within a ToolTip would also become green, what would be probably fairly surprising for many devs.
I usually work around this by either defining resources as application resources within the App.xaml or use something I would call resource nesting.
Either directly on the control in question:
<ContentPresenter Content="Foo">
<ContentPresenter.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}" />
</ContentPresenter.Resources>
</ContentPresenter>
Or by deeper nesting in the resources:
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Green" />
</Style>
<Style TargetType="ContentPresenter">
<Style.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}" />
</Style.Resources>
</Style>
</Window.Resources>
Just for completeness, in case anyone is wondering, depending on the structure of the elements to style, the nesting can become fairly deep, so to apply the styling to text within a ToolTip, it would be necessary to write something like:
<Window.Resources>
<Style Type="ToolTip">
<Style.Resources>
<Style TargetType="ContentPresenter">
<Style.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}" />
</Style.Resources>
</Style>
</Style.Resources>
</Style>
</Window.Resources>
@batzen, I think what @MichaeIDietrich is saying here is right.
I went through some specs and some other forums, and this is a known decision taken by the team.
If the element being implicitly styled is not a subclass of Control, the implicit style lookup will not look beyond the templated parent’s template. (This is so users do not accidentally style controls they don’t even realize exist – such as a DockPanel buried deep inside the template for Button)
If the element being implicitly styled is not a subclass of Control, the implicit style lookup will not look beyond the templated parent’s template. (This is so users do not accidentally style controls they don’t even realize exist – such as a DockPanel buried deep inside the template for Button)
Well users can accidentally do this by defining it at the app level. So your explanation seems counter intuitive.
If i define one style for TextBlock at the app level and one at the window level, for example, i expect the window defined style to be preferred. But instead the style from the app level is chosen. That's just unexpected.
I think letting it check App.xaml is a way to let people override this behaviour if they really want it. There are other ways we can bypass this - https://stackoverflow.com/a/70357158/14917248
Also, if I am not wrong, implicit-style lookup does not go and look into theme dictionary. I can be wrong here, haven't checked it and the docs are too old ( the specs may have changed a bit over time )
@dipeshmsft And the next user being confused about this restriction. See #9029
Can't we just add a lookup for the current Window also? Implicit style lookup, in this case, jumps to app and then to the theme dictionary. If this issue isn't fixed it will causes issues with window level Fluent themes also.