问题 在WPF中,如何在代码中引用资源库中的字体?


我有一个应用程序使用单独的库程序集资源(但不是一个没有代码的资源专用程序集),我想在库中包含一个自定义字体。

我能够得到字体,这是一个 Open Type Font,如果我将其.otf文件作为资源添加到执行程序集的项目(而不是资源库项目),并将属性设置为Build Action ='Resource'并复制到Output ='Do Not Copy',则加载,使用以下代码:

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

但是,当我尝试将字体添加到资源库项目时,不会加载字体。我尝试使用以下代码加载它(另请注意:我对pack URI没有太多经验):

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 .

该库适用于其他资源,例如图像。

我还尝试了一堆URI的其他排列没有成功(它也不会抛出异常,只显示默认字体,不确定这是否是一个单独的问题)。

我一直在工作 包含应用程序的字体 在MSDN上,它有一个创建字体资源库的例子,但没有使用代码的示例(我被迫使用后面的代码)。

关于我需要做什么的任何想法?我偏离轨道吗?


5155
2018-05-09 19:17


起源



答案:


我在我的应用程序中工作(从代码隐藏中的另一个程序集加载字体)。对于像这样的字体URI:

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

我让它工作的方式(经过痛苦的试验和错误,如果我没记错的话)是:

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

希望有所帮助。


14
2018-05-09 20:19



这对我不起作用,这表明我有一些其他问题因为它适合你。 - Pysul
谢谢,对我而言,它起作用了......给了我很多试验和错误! - yvesonline
我可以确认它完美无缺,在我尝试了太多的加载组合之前没有成功!我认为从dll内部对资源的相对访问就足够了,但即使应该从同一个程序集访问字体,显然也需要添加程序集名称! - too
为了更加重构,我还决定在运行时获取程序集名称,在TTF文件旁边放置一个虚拟类: string fontAssemblyName = Assembly.GetAssembly(typeof(FontPlaceholder)).GetName().Name; 然后组合文本结果: String.Format("pack://application:,,,/{0};component/Resources/Fonts/", fontAssemblyName); - superjos
请注意,嵌入字体的内存泄漏方式如下: stackoverflow.com/questions/31452443/... - Osi


答案:


我在我的应用程序中工作(从代码隐藏中的另一个程序集加载字体)。对于像这样的字体URI:

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

我让它工作的方式(经过痛苦的试验和错误,如果我没记错的话)是:

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

希望有所帮助。


14
2018-05-09 20:19



这对我不起作用,这表明我有一些其他问题因为它适合你。 - Pysul
谢谢,对我而言,它起作用了......给了我很多试验和错误! - yvesonline
我可以确认它完美无缺,在我尝试了太多的加载组合之前没有成功!我认为从dll内部对资源的相对访问就足够了,但即使应该从同一个程序集访问字体,显然也需要添加程序集名称! - too
为了更加重构,我还决定在运行时获取程序集名称,在TTF文件旁边放置一个虚拟类: string fontAssemblyName = Assembly.GetAssembly(typeof(FontPlaceholder)).GetName().Name; 然后组合文本结果: String.Format("pack://application:,,,/{0};component/Resources/Fonts/", fontAssemblyName); - superjos
请注意,嵌入字体的内存泄漏方式如下: stackoverflow.com/questions/31452443/... - Osi


WPF不支持使用包符号以编程方式创建FontFamily对象。

文档在页面末尾说出来, 这里

这是引用:

使用包的绝对URI:表示法: WPF应用程序不允许您使用“pack:”以编程方式创建FontFamily对象,作为对字体的绝对统一资源标识符(URI)引用的一部分。例如,“pack:// application:,,, / resources /#Pericles Light”是无效的字体引用。


1
2018-03-30 13:45



那为什么它适合某些人呢? - IneedHelp
好吧,没有看代码,我甚至无法理解。但文档说它没有。我会说文档是可信的:) - Ninglin
我的意思是上面帖子中的人说他们设法让它发挥作用,但你是对的,文档具有更高的可信度。 - IneedHelp
它的措辞并不特别好。但我的猜测是你不能直接在URI中指定姓氏。您将URI作为“基本”位置传递,然后指定系列名称。请参阅该页面上的示例。 - Nigel Whatling
将字体打包为资源(不是嵌入式资源),不要复制,只需引用xaml中的字体,如<FontFamily x:Key =“”> ./# My Font </ FontFamily>(在本例中不在任何子文件夹中)适合我。 - dudeNumber4


(我知道,老问题,但我找不到正确的答案。)

Ross的答案仅适用于某些版本的netframework。 (不适用于netframework 4.6)

我认为这是最好的答案:

枚举应用程序中的字体:

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

参考


0
2018-02-11 21:48