Using multiple styles on elements in XAML (Windows 8/WP7)

XAML styles are great for creating formatting and general properties setters that can be applied to elements in your UI easily.

They are used massively in Windows Phone, Windows 8 and Silverlight as well as in WPF. (Note that some conditional compilation occurs to account for the difference between Win8 XAML and WP XAML.

One of the major drawbacks of using Styles is that you cannot combine them – there’s no way to apply more than one style to an element. There are a bunch of ways around this, however, at the end of the day, most people end up in-lining some of the styles. It is possible to “inherit” styles, but then you immediately gain all the properties you are based on, which is not always desirable.

An example of this would be if you had the following styles:

  1. headerStyle – Used by you to specify large text that needs to be very visible.
  2. textForMessageStyle – Used when you have text that might run-off and you want to wrap it and put an ellipsis at the end of it.
  3. centeredStyle – Used for centering text – VerticalAlignment and TextAlignment are set to Center while HorizontalAlignment is set to Stretch.

To address this, I wrote the CompoundStyle class which lets you take a bunch338064_8618 of styles and combine them to one style which can be used. There are three ways of using the class – and usage depends on your situation.

Note that CompoundStyle has one major draw-back and that is that it cannot be dynamically changed. Once assigned, it will be “frozen”. If you bind your styles, this will probably not be good enough for you. You should be able to rework the code and define some of the objects as DependencyObjects and implement them as Dependency properties (specifically in the StyleHolder class).

Creating a style based on multiple styles

If you wish to create a compound style in your resource dictionary, that’s fairly easy:

<local:CompoundStyle 
x:Key="compoundStyle1"
Style1="{StaticResource headerStyle}"
Style2="{StaticResource textForMessageStyle}"
Style3="{StaticResource centeredStyle}"/>

Using the style is slightly different than using a style that’s in a resource:

<TextBlock 
Text="Test"
Style="{Binding Source={StaticResource compoundStyle1}, Path=Style}"/>

Since the Style class is sealed, there’s no way to just inherit it and let developers simply reference the style, sadly. Instead, we bind by defining what the source is (our resource) and specify the property that contains the compound style (Style).

The properties Style1, Style2, Style3, Style4, Style5 allow you to apply up to 5 styles in “short-hand”. If you need more styles, you can use the BasedOnStyles collection instead:

<local:CompoundStyle x:Key="compoundStyle2">
<local:CompoundStyle.BasedOnStyles>
<local:StyleHolder Style="{StaticResource headerStyle}"/>
<local:StyleHolder Style="{StaticResource textForMessageStyle}"/>
<local:StyleHolder Style="{StaticResource centeredStyle}"/>
</local:CompoundStyle.BasedOnStyles>
</local:CompoundStyle>

 

Directly attaching compound style (no resource)

If you wish to specify your compound style, but not as a resource, but directly on the element, you can do that too. It’s possible to just use the attached property Attached to set a CompoundStyle onto an element:

<TextBlock Text="Test">
<local:CompoundStyle.Attached>
<local:CompoundStyle
Style1="{StaticResource headerStyle}"
Style2="{StaticResource textForMessageStyle}"
Style3="{StaticResource centeredStyle}"/>
</local:CompoundStyle.Attached>
</TextBlock>

Directly attaching with just style names

Finally, there’s an even shorter method of attaching styles to an element via the StyleKeys attached properties. This method has three disadvantages to it:

  1. It’s not “type safe”. That is to say – the compiler and designer will not warn you that something is wrong if you mistype the key of a resource or something.
  2. It only gets applied AFTER the element is loaded. This should not cause any major problems, but it’s worth being aware of.
  3. If your resource name has a comma in it, this mechanism will fail you (seriously – who puts a comma in a resource name? What are we? Animals?)

Here’s how you apply the styles when using this method:

<TextBlock 
Text="Test"
local:CompoundStyle.StyleKeys="headerStyle,textForMessageStyle,centeredStyle"/>

That’s pretty much it! You can download the code here.

(Note – if the Phone solution is not working for you, just copy the files over to a new project created in VS2010)

About these ads
This entry was posted in Dev, Windows8, WindowsPhone and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s