Cascading Implicit Styles in WPF

Posted by: Clarity Blogs: ASP.NET, on 27 Jul 2009 | View original | Bookmarked: 0 time(s)

I was all set to write a post detailing a cumbersome workaround for getting implicit styles to cascade in WPF, when I figured out theres an easier way. Actually, I think its probably common knowledge to a lot of people, but I figured I should post it here in case anyone (like me) is in the dark. (After digging around a little, I couldnt find anything about this in the Sells book. Its hinted at on p. 315 of WPF Unleashed, but not stated explicitly.)

Implicit style in WPF are styles you dont need to refer to by name. They simply apply to all elements in scope belonging to the specified type. An example will help.

Suppose Im writing a new app, and I decide that every TextBlock should have red text. (Warning: I am not a designer.) I might create a style like this in my App.xaml:

<Application.Resources>
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Red" />
    </Style>
</Application.Resources>

Note that we do not specify a key on the style. We dont need to. We do need to make sure to specify the target type; otherwise, WPF cant know which elements we want this style to apply to. Lets drop some code in to test that this works:

<StackPanel>
    <Grid>
        <TextBlock Text="where my implicit styles at" />
    </Grid>
    <Grid Grid.Row="1">
        <TextBlock Text="where my implicit styles at" />
    </Grid>
</StackPanel>
If we run the app, we can see that it works:

image

Perfect. Now, suppose I want to add another style to apply only to some of my text. I might scope it like this:

<StackPanel>
    <Grid>
        <Grid.Resources>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="FontSize" Value="24" />
            </Style>
        </Grid.Resources>
        <TextBlock Text="where my implicit styles at" />
    </Grid>
    <Grid Grid.Row="1">
        <TextBlock Text="where my implicit styles at" />
    </Grid>
</StackPanel>
Ive created another implicit style to increase the font size of any TextBlocks I place in the top Grid. Lets try running this and see what happens.

image

Hmm. Thats not quite what we wanted. Our new implicit style seems to have overridden the old one. To understand why, we need to think a little bit about how implicit styles actually work. When we specify a style explicitly, WPF walks up the chain of resource dictionaries and looks for one with the specified key. It returns the first (most local) one it finds. In light of this, its not clear how our implicit styles get applied, since we didnt specify any keys for them. If we think about it a little, we can work it out.

We know the styles have to have some keys; otherwise, how would they fit into the resource dictionaries? Whats not clear is how the key is chosen. One might suspect some randomly generated value to serve as the key, but the answer is much simpler: the target type is the key. (This is mentioned on p. 315 of WPF Unleashed.) Armed with this knowledge, we can easily understand implicit styles. For any elements where the style is not explicitly specified, look for the elements type in the resource dictionary chain and return the most local one you find. So in our example, we have two such styles: one at the application level and one scoped just to the Grid. It finds the local style first and stops looking.

Now that we have a good understanding of the problem, the solution is pretty obvious. Since we know our implicit style does have a key, we can use it as a base for our new style like this:

<StackPanel>
    <Grid>
        <Grid.Resources>
            <Style TargetType="{x:Type TextBlock}" 
                   BasedOn="{StaticResource {x:Type TextBlock}}">
                <Setter Property="FontSize" Value="24" />
            </Style>
        </Grid.Resources>
        <TextBlock Text="where my implicit styles at" />
    </Grid>
    <Grid Grid.Row="1">
        <TextBlock Text="where my implicit styles at" />
    </Grid>
</StackPanel>

Well run the app to make sure it works:

image

Neat.

This isnt a perfect solution, since we still need to be aware when were stomping on our previous styles, but I think the benefits of implicit styles are more than worth the price.

Like I said, Im sure a lot of people know about this already, but I was oblivious until now, so I thought Id share.

Hope this helps.

 

EDIT: Just as an addendum, I want to point out that you can have implicit styles with explicit keys. You just need to make sure that the key is the same as it would be if generated implicitly; that is, the key must be the target type. So when you see code like this:

<Application.Resources>
    <Style x:Key="{x:Type TextBlock}" TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Red" />
    </Style>
</Application.Resources>

Understand that this is still an implicit type.

Hope this helps.

Advertisement
Free Agile Project Management Tool from Telerik
TeamPulse Community Edition helps your team effectively capture requirements, manage project plans, assign and track work, and most importantly, be continually connected with each other.
Category: WPF | Other Posts: View all posts by this blogger | Report as irrelevant | View bloggers stats | Views: 2358 | Hits: 16

Similar Posts

  • CSS isolation: there has got to be a better way more
  • nxslt3.exe/NxsltTask v3.0 - now running compiled XSLT stylesheets more
  • VS 2008 Web Designer and CSS Support more
  • Asynchronous Data Binding in Windows Presentation Foundation more
  • Host WPF Controls in Windows Forms more
  • Using WPF, Virtual Earth, and WPF/E together... more
  • WPF Styles: EventSetters more
  • More WPFE, Virtual Earth, and AJAX goodness! more
  • WPF/E and Script# more
  • Introducing Fluent Control Container more

News Categories

.NET | Agile | Ajax | Architecture | ASP.NET | BizTalk | C# | Certification | Data | DataGrid | DataSet | Debugger | DotNetNuke | Events | GridView | IIS | Indigo | JavaScript | Mobile | Mono | Patterns and Practices | Performance | Podcast | Refactor | Regex | Security | Sharepoint | Silverlight | Smart Client Applications | Software | SQL | VB.NET | Visual Studio | W3 | WCF | WinFx | WPF | WSE | XAML | XLinq | XML | XSD