30 Aug
Microsoft has provided some very good documentation on how to package fonts with WPF applications, and I’ve been following it in several different ways in different apps I’ve written. Recently I provided a feature in Posh Console which allows you to load the startup banner from an external file: StartupBanner.xaml.
Loading the banner from an external XAML file means that users can configure their own startup banner and make it look however they like, but it broke our default banner. The startup banner we’ve been using has a logo and some text which are all defined in pure XAML and uses several fonts which we had embedded in a FontLibrary.dll resource assembly. It worked great as long as the XAML was defined in the application, but as soon as we removed it to an external file and loaded it in using the XamlReader.Load method, the fonts all went to the fallback default fonts instead of our embedded ones.
Normally this might not be a big deal, but since our logo is based on the “Q” in a Quake-like font … it looks really lame without fonts.
Apparently, when you load external XAML, it can’t use the Font Resource Library resources. At this point, I can’t seem to find anything to indicate why this is the case, but I suspect it has to do with the fact that the external, loaded XAML only has partial trust, and since the font is in an external assembly instead of embedded in the partial trust content, it can’t get to it. However, it might be simpler than that: it might just be that the base URI for the externally loaded XAML is an actual file location rather than one of the pack://,,,application/ type URIs, so the slightly odd font path doesn’t resolve.
In any case, I found a way around it, which is of course, why I’m writing all of this down.
If you declare WPF resources in your project, you can inject them into the WPF objects loaded from the XAML to make them available to them. So for instance, I have a font called “Quake” in the FontLibrary assembly. I can declare it as a resource in my application’s XAML (at the app level, window level, or wherever).
The font in that style gets resolved in full trust with the pack URI, and it works fine when used from my application. Having created that, I can do the same thing in the external XAML files, and apply the style to the text as a DynamicResource … and even feel free to override parts of the style if I want to. For instance, even though the style might specify a FontSize, if I refer to the style on this text block and specify my own FontSize, the one that’s on the TextBlock (or Paragraph, or Run, or whatever) will be used. Now, we’re not quite done yet, because although they look the same in source, the fonts won’t resolve properly in the externally loaded XAML.
However, because the style is specified as a dynamic resource rather than a static one, I don’t have to define that resource at all in that XAML file, but even if I do, when I load the XAML into my application, I can simply set it’s resources from the resources that I’ve loaded in full trust and with the pack:// base URI... In my case, I have actually defined several fonts as resources on a Document element, so I just copy them all into the element I read in from the XAML file:
Add New Comment
Viewing 4 Comments
Thanks. Your comment is awaiting approval by a moderator.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Add New Comment
Trackbacks