15

I have an application that uses a separate library assembly for resources (but not a resource-only assembly with no code), and I would like to include a custom font in the library.

I am able to get the font, which is an Open Type Font, to load if I add its .otf file as a resource to the project for the executing assembly (rather than to the resource library project), with properties set as Build Action = 'Resource' and Copy to Output = 'Do Not Copy', by using the following code:

FontFamily font = new FontFamily(new Uri("pack://application:,,,/"), 
                      "./Resources/#CustomFont")); // Resources is a subfolder

When I try to add the font to the resource library project, however, the font does not load. I tried using the following code to load it (also of note: I do not have much experience with pack URIs):

FontFamily font = new FontFamily(new Uri("pack://application:,,,/MyLibrary"),
                      "./Resources/#CustomFont")); 
                      // there is a Resources subfolder in my library as well
                      // not sure about whether I need the .

The library does work for other resources, such as images.

I've also tried a bunch of other permutations for the URI with no success (it also does not throw exceptions, just displays with the default font, not sure if this is a separate issue).

I've been working from Packaging Fonts with Applications on MSDN, which has an example of creating a font resource library, but no examples using code behind (I am forced to use code behind for this).

Any ideas about what I need to do? Am I off track?

axanpi
  • 731
  • 9
  • 16

4 Answers4

22

I have it working in my application (loading fonts from another assembly in code-behind). For a font URI like this:

pack://application:,,,/MyAssembly.Name;component/Resources/Fonts/#Swis721 Md BT

The way I got it to work (after painful trial and error, if I remember correctly) is:

new FontFamily(
    new Uri("pack://application:,,,/MyAssembly.Name;component/Resources/Fonts/"),
    "./#Swis721 Md BT"
)

Hope that helps.

Ross
  • 4,460
  • 2
  • 32
  • 59
  • This did not work for me, which suggests I have some other problem since it's working for you. – axanpi May 09 '12 at 20:55
  • 1
    Thanks, for me it worked... saved me a lot of trial and error! – yvesonline Apr 24 '13 at 13:19
  • I can confirm it works perfectly and before I tried far too many combinations of loading without success!!! I thought a relative access to resources from within dll would be enough but apparently adding assembly name is required even if fonts should be accessed from the same assembly! – too Sep 30 '14 at 12:55
  • In order to be more refactor-friendly, I also decided to get the assembly name at runtime putting a dummy class next to TTF files: `string fontAssemblyName = Assembly.GetAssembly(typeof(FontPlaceholder)).GetName().Name;` and then combine text result: `String.Format("pack://application:,,,/{0};component/Resources/Fonts/", fontAssemblyName);` – superjos Jul 02 '15 at 09:36
  • 1
    Please note that there is a memory leak related to embedding fonts that way: http://stackoverflow.com/questions/31452443/wpf-textblock-memory-leak-when-using-font – Zsolt Feb 09 '16 at 10:28
  • It seems that the key is having a trailing slash in the base URI parameter and also having a dot before the leading slash in the family name parameter. I tried with only one or the other, and neither worked. I needed both... – Adam Goodwin Mar 27 '20 at 19:57
1

WPF does not support creating the FontFamily object programmatically using pack notation.

The docs say it in the end of the page, here

Here is the quote:

Absolute URI using the pack: notation: WPF applications do not allow you to create a FontFamily object programmatically using "pack:" as part of the absolute uniform resource identifier (URI) reference to a font. For example, "pack://application:,,,/resources/#Pericles Light" is an invalid font reference.

Ninglin
  • 146
  • 1
  • 9
  • Well, without looking at the code I couldn't even begin to comprehend. But the docs say it does not. I would say the docs are to be trusted :) – Ninglin Nov 27 '15 at 14:21
  • I mean the guys in the post above say they managed to make it work, but you're right, the documentation has more credibility. – IneedHelp Nov 27 '15 at 16:59
  • 1
    It's not worded particularly well. But my guess would be that you cannot specify the family name directly in the URI. You pass a URI as a 'base' location and then specify the family name. See examples further up that page. – Nigel Whatling Jul 18 '16 at 11:50
  • Packaging the font as resource (not embedded resource), do not copy, and simply referencing the font in xaml like ./#My Font (not in any subfolder in this case) works for me. – dudeNumber4 Oct 19 '16 at 12:30
  • I had some problems with it, too. But interestingly I got it to work in my test project. It is a WPF project using .Net 4.6.1 (maybe .1 makes the difference?) I am using it in code like so: `new FontFamily(new Uri("pack://application:,,,/"), "./Fonts/#Encode Sans");` while Fonts is a folder and the whole typeface set of Encode Sans is added to the project as "Resource" "Don't copy" -- it's worth noting that "Embedded Resource" does NOT work – Robetto Jan 15 '19 at 10:46
0

(I know, old question, but I didn't find a correct answer.)

the Ross's answer only works in some versions of the netframework . (Does not work on netframework 4.6)

I think this is the best answer :

Enumerating Fonts in an Application :

 foreach (FontFamily fontFamily in Fonts.GetFontFamilies(new Uri("pack://application:,,,/"), "./resources/"))
            {
                // Perform action.
            }

reference

Maria
  • 344
  • 8
  • 30
0

In order to reference font resource items from code, you must supply a two-part font resource reference: the base uniform resource identifier (URI); and the font location reference. These values are used as the parameters for the FontFamily method. The following code example shows how to reference the application's font resources in the project subdirectory called resources.

// The font resource reference includes the base URI reference (application directory level),
// and a relative URI reference.

myTextBlock.FontFamily = new FontFamily(new Uri("pack://application:,,,/"), "./resources/#Pericles Light");

The base uniform resource identifier (URI) can include the application subdirectory where the font resource resides. In this case, the font location reference would not need to specify a directory, but would have to include a leading "./", which indicates the font resource is in the same directory specified by the base uniform resource identifier (URI). The following code example shows an alternate way of referencing the font resource item—it is equivalent to the previous code example.

// The base URI reference can include an application subdirectory.

myTextBlock.FontFamily = new FontFamily(new Uri("pack://application:,,,/resources/"), "./#Pericles Light");

Source: learn.microsoft.com

ynsbl.eng
  • 142
  • 2
  • 8