Sunday, April 14, 2024

XAML Style Dictionaries

Step by step: adding consistent styles to a XAML app

XAML has a useful feature where you can set up a single file with a bunh of "style" configuration for your XAML (UWP) app, and then use those styles everywhere in your app. The plus side is having a centralized style configuration: all your titles can be one size, and all your technical text has the correct font, and all. The downside is that getting it set up is buried in a blizzard of docs. There's a lot of ways to set up your XAML styles, and Microsoft wants you to fully understand each of them in isolation.

In this simple blog post, I walk through the steps of one way to add centralized styles to your app and then be able to use them everywhere.

Create an AppDictionary.xaml file. In your project, Add > New and add a XAML ResourceDictionary. Call is AppDictionary.xaml.

Add your first style. I tend to prefix all my centralized styles with a small "s" like "sTitle".

    <Style x:Key="sTitle" TargetType="TextBlock">
        <Setter Property="FontWeight" Value="Bold" />
        <Setter Property="FontSize" Value="24" />
    </Style>    

Update the App.Xaml file to include this:

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
                <ResourceDictionary Source="AppDictionary.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

The XamlControlsResources is seemingly a new thing for the Toolkit; it's essential to make the toolkit work. At least, that what is looks like to me.


Original, bad way: Update every page and control to include the AppDictionary

    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="AppDictionary.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

This isn't as good as just updating the App.Xaml because you have to update every page. By updating the App.Xaml file, you do it just once. At least, that's what I think will happen. If I was really an expert on this stuff, I wouldn't have struggled with it for a couple of hours last night :-)

Use the new style.  In a textblock, set the Style to be {StaticResource sTitle}.

        <TextBlock Style="{StaticResource sTitle}">Thingy Data</TextBlock>

Now you're styling with style, and it just took one short blog post to replaces multiple lengthy pages of explanation from the learn.microsoft.com site!


Weird Error to be aware of:

In my original App.Xaml file, I had the <Style> items right there in the file and then had the Resource Dictionary. But that could only be made working XAML by adding a "x:Key=..." to the ResourceDictionary. For a long time, this worked fine, but when I updated to the latest Toolkit, I got the following error. 

Windows.UI.Xaml.Markup.XamlParseException: 'The text associated with this error code could not be found.

Cannot find a Resource with the Name/Key ExpanderHeaderBackground [Line: 100 Position: 26]'


As far as I can tell, the "x:Key" is needed because when you have <Style> items in the <Application.Resources>, it's like it makes a default <ResourceDictionary>. So when you make a second <ResourceDictionary>, you have to give it a name.

But that's just a guess. What I know is that when I got the above error, I had an x:Key in my <ResourceDictionary> that I used for including the <XamlResourceControls> and when I moved everything around so I didn't need th x:Key, my app stopped crashing.

No comments: