开发时突然发现,跨程序集引用字体文件时总是不生效,于是根据这个问题用AI总结了一个关于Uri的知识点。
它直接给出了NSDN中的明确说明。

🎯 WPF 资源 URI 使用总结
一、WPF 资源定位的两套体系
WPF 有两种不同的资源定位机制:
| 系统 |
用途 |
典型类型 |
解析逻辑 |
| XAML 资源系统 |
图片、样式、模板等 |
ImageSource, ResourceDictionary, Style, ControlTemplate |
相对路径相对于 XAML 文件所在位置解析 |
| FontFamily 系统 |
字体文件(.ttf / .otf) |
FontFamily |
不继承 XAML BaseUri,只根据程序集名或绝对 URI 解析 |
👉 这就是为什么字体在跨程序集时需要显式指定程序集,而图片等普通资源不需要。
二、几种常见 URI 写法对比
| 写法 |
示例 |
含义 |
同程序集 |
跨程序集 |
备注 |
./Assets/... |
./Assets/Fonts/xxx.ttf |
相对路径,相对于当前 XAML 文件的目录 |
✅ 可用 |
⚠️ 字体类资源 ❌ |
适合样式、图片等;字体跨程序集会失效 |
/Assets/... |
/Assets/Fonts/xxx.ttf |
根路径,相对于主程序程序集 |
✅ 在主程序集内可用 |
❌ |
主程序内部可用,其他程序集引用无效 |
/AssemblyName;component/... |
/Common;component/Assets/Fonts/... |
明确指向特定程序集的资源路径 |
✅ |
✅ |
可用于任何资源,包括字体 |
pack://application:,,,/AssemblyName;component/... |
pack://application:,,,/Common;component/Assets/Fonts/... |
完整的 pack URI,官方推荐格式 |
✅ |
✅ |
最稳妥、最通用的写法 |
pack://siteoforigin:,,,/Assets/... |
pack://siteoforigin:,,,/Assets/Fonts/... |
从应用程序运行目录加载外部文件 |
⚠️ |
⚠️ |
适合动态加载外部资源(非嵌入资源) |
三、典型资源场景总结表
| 资源类型 |
推荐 URI 写法 |
原因与说明 |
| 图片(ImageSource) |
./Assets/Images/xxx.png |
继承 BaseUri,相对路径即可跨程序集生效 |
| 样式 / 控件模板 (ResourceDictionary) |
/AssemblyName;component/... |
方便跨程序集引用样式库 |
| 字体 (FontFamily) |
pack://application:,,,/AssemblyName;component/Assets/Fonts/#字体名 |
FontFamily 不继承 BaseUri,需显式指定程序集 |
| 外部配置文件(非嵌入) |
pack://siteoforigin:,,,/config.json |
用于程序运行目录下的外部文件 |
| 控件库中的样式主题(Themes/Generic.xaml) |
/AssemblyName;component/Themes/Generic.xaml |
WPF 自动加载时依赖此格式 |
四、字体的特殊性(你这次问题的核心)
| 情况 |
相对路径 |
绝对路径(带程序集) |
结果 |
| 字体在同程序集使用 |
✅ 正常 |
✅ 正常 |
都能找到 |
| 字体在其他程序集引用 |
❌ 失效 |
✅ 正常 |
FontFamily 不继承 BaseUri |
| 图片在其他程序集引用 |
✅ 正常 |
✅ 正常 |
ImageSource 继承 BaseUri |
所以你的 ./Assets/Fonts/... 在 Common 内当然能显示,
但被 MesDemo 调用后就变成默认字体(解析上下文切换)。
五、几种 Pack URI 的分层理解(便于记忆)
| URI 前缀 |
查找位置 |
常见用途 |
pack://application:,,,/ |
当前应用或指定程序集的嵌入资源 |
核心、最常用 |
pack://siteoforigin:,,,/ |
应用运行目录下外部文件 |
动态加载外部资源 |
/AssemblyName;component/... |
简写形式,会被解析成上面的 application URI |
推荐跨程序集资源引用 |
/Assets/... |
主程序集资源根路径 |
仅限单程序集应用 |
六、实际项目中推荐习惯
| 场景 |
推荐用法 |
示例 |
| 多程序集项目(样式库 + 主程序) |
统一使用带程序集的 URI |
/MyLibrary;component/Resources/Colors.xaml |
| 字体引用(跨程序集) |
使用完整 pack URI |
pack://application:,,,/UIResources;component/Assets/Fonts/#FontName |
| 主程序资源(单程序集) |
简写路径 /Assets/... 即可 |
/Assets/Styles/MainTheme.xaml |
| 外部加载(如用户皮肤) |
使用 siteoforigin |
pack://siteoforigin:,,,/Themes/UserTheme.xaml |
七、速查对照(最实用部分)
| 目标 |
写法 |
适用范围 |
| 主程序集样式 |
/Assets/Styles/Main.xaml |
当前程序内 |
| 外部样式库 |
/Common;component/Assets/Resources/TextResource.xaml |
跨程序集 |
| 字体(同程序集) |
./Assets/Fonts/#FontName |
当前程序集 |
| 字体(跨程序集) |
pack://application:,,,/Common;component/Assets/Fonts/#FontName |
推荐写法 |
| 外部图片(非嵌入) |
pack://siteoforigin:,,,/Images/bg.png |
程序外部资源 |
八、可视化总结(逻辑关系图)
WPF 资源定位系统
├── XAML Resource System
│ ├── 相对路径 (./)
│ ├── 绝对路径 (/)
│ └── 程序集路径 (/Assembly;component/)
│
└── FontFamily System ← 字体是特例
├── 不继承 XAML BaseUri
├── 需显式 pack://application:,,,/Assembly;component/
└── 内部解析 #FontName
✅ 总结一句话记忆
普通资源(图片、样式)看 XAML 的位置,字体资源看程序集的位置。
👉 跨程序集时,pack://application:,,,/Assembly;component/... 是万能解法。