| 維度 | 二進制資源 | 邏輯資源 |
|---|---|---|
| 本質 | 圖片、音訊、字型、松散檔案 | .NET 物件(Brush、Style、Template、ViewModel 等) |
| 建置動作 | Resource (嵌入組件) / Content (松散檔) | 無,直接在 XAML Resources 區塊宣告 |
| 引用方式 | Pack URI(pack://application:,,,/Images/logo.png) | {StaticResource key} / {DynamicResource key} |
| 本地化 | 衛星組件 | ResourceDictionary 切換 |
建議:UI 圖示、啟動畫面用 Resource;大型媒體、頻繁更新檔案用 Content;避免 EmbeddedResource(WPF Pack URI 無法直接存取)。
Images/logo.png // 專案內 Resource/Content 相對路徑
/SubFolder/Images/logo.png // 專案根目錄相對路徑
pack://application:,,,/MyLib;component/Images/logo.png // 參考組件 Resource
pack://siteoforigin:,,,/Images/logo.png // 部署根目錄 Content (不打包進組件)
file:///C:/Data/logo.png // 絕對檔案系統路徑
| 特性 | StaticResource | DynamicResource |
|---|---|---|
| 解析時機 | 載入 XAML 時一次性查找 | 每次存取屬性時即時查找 |
| 前向引用 | 不支援(資源必須在前面定義) | 支援(資源可在後面定義) |
| 運行時更新 | 不反映 | 自動反映(ResourceDictionary 內容變更) |
| 效能 | 極佳(單次查找) | 稍高(每次查找走邏輯樹) |
| 適用目標 | 任何屬性、非 DependencyProperty | 僅 DependencyProperty |
| 系統資源 | 不可用 | 必要({DynamicResource {x:Static SystemColors.WindowBrushKey}}) |
決策口訣:預設用 StaticResource;需運行時換膚、引用系統資源、前向引用時改 DynamicResource。
StaticResource:元素 Resources → 邏輯樹父元素 Resources → App/Window/Page Resources → 系統資源。
DynamicResource:元素 Resources → 邏輯樹父元素 → App Resources → 當前主題 Theme Resources → 系統資源。
程式碼存取:element.Resources["key"]、element.FindResource("key")(找不到拋例外)、element.TryFindResource("key")(回傳 null)。
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/LightBrushes.xaml"/>
<ResourceDictionary Source="Common/SharedStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- 本視窗專用覆寫 -->
<SolidColorBrush x:Key="AccentBrush" Color="Orange"/>
</ResourceDictionary>
</Window.Resources>
合併順序決定優先權:後合併者勝出。執行時動態切換:
var dict = Application.LoadComponent(new Uri("Themes/DarkBrushes.xaml", UriKind.Relative)) as ResourceDictionary;
App.Current.Resources.MergedDictionaries.Clear();
App.Current.Resources.MergedDictionaries.Add(dict); // 瞬間全域換膚
Resources/en-US.xaml、Resources/zh-TW.xaml,鍵值相同,值為當地語系字串。<ResourceDictionary Source="Resources/en-US.xaml"/>。protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);
var culture = CultureInfo.CurrentUICulture.Name; // 如 "zh-TW"
var dict = Application.LoadComponent(new Uri($"Resources/{culture}.xaml", UriKind.Relative)) as ResourceDictionary;
if (dict != null) {
Resources.MergedDictionaries.Clear();
Resources.MergedDictionaries.Add(dict); // 後加入者優先,覆蓋預設
}
}
<TextBlock Text="{StaticResource Title_Home}"/>。測試切換:Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-TW"); 重啟 App 即見中文介面。
<Style TargetType="{x:Type Button}"> <!-- 無 x:Key,TargetType 即為隱性鍵 -->
<Setter Property="Background">
<Setter.Value><LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="AliceBlue"/>
<GradientStop Offset="1" Color="Salmon"/>
</LinearGradientBrush></Setter.Value>
</Setter>
<Setter Property="FontSize" Value="14"/>
</Style>
範圍內所有 Button 自動套用,除非显式設定 Style={x:Null} 或另覆寫 Style。配合 BasedOn 可建立樣式繼承鏈。
類別庫定義:
public static class MyResources {
public static readonly ComponentResourceKey AccentBrushKey =
new ComponentResourceKey(typeof(MyResources), "AccentBrush");
}
資源字典:<SolidColorBrush x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:MyResources}, ResourceId=AccentBrush}" Color="Teal"/>
消費端引用:<Button Background="{DynamicResource {x:Static local:MyResources.AccentBrushKey}}"/>
<Button x:Key="btnTemplate" x:Shared="False" Content="範本按鈕"/>
<StackPanel>
<StaticResource ResourceKey="btnTemplate"/> <!-- 實例 A -->
<StaticResource ResourceKey="btnTemplate"/> <!-- 實例 B,獨立可修改 -->
</StackPanel>
適用於需在多處使用但需獨立狀態的視覺元素(如彈出式選單模板)。