我正在寻找一种方法来定义可从我的应用程序中的任何位置访问的 WPF 资源(目前,用作静态资源)。
我的资源在此资源字典中定义:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="flatButtonStyle" BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" TargetType="{x:Type Button}">
<Setter Property="BorderThickness" Value="4"/>
</Style>
</ResourceDictionary>
此问题的选定答案表明我必须将该资源字典合并到我的App.xaml
文件(名为 的项目AppWideResources
)中:
<Application x:Class="AppWideResources.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/AppWideResources;component/CommonResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
起初,这似乎有效。此窗口中的按钮以带有超厚边框的扁平方式适当地设置样式:
<Window x:Class="AppWideResources.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AppWideResources" Height="300" Width="300"
>
<StackPanel>
<Button Style="{StaticResource flatButtonStyle}" Content="Test" HorizontalAlignment="Stretch"/>
</StackPanel>
</Window>
但是,一旦我在控制模板中使用我的共享资源,这将停止工作:
我的(出于这个问题的目的,非常简化)控制:
using System;
using System.Windows;
using System.Windows.Controls;
namespace AppWideResources
{
public class MyControl : Control
{
static MyControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));
}
}
}
...和相应的Themes\Generic.xaml
文件:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AppWideResources">
<Style TargetType="local:MyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyControl">
<StackPanel Orientation="Horizontal">
<Button Style="{StaticResource flatButtonStyle}" Content="1"/>
<Button Style="{StaticResource flatButtonStyle}" Content="2"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
然后将此控件插入到我的窗口中:
<Window x:Class="AppWideResources.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AppWideResources"
Title="AppWideResources" Height="300" Width="300"
>
<StackPanel>
<Button Style="{StaticResource flatButtonStyle}" Content="Test" HorizontalAlignment="Stretch"/>
<local:MyControl/>
</StackPanel>
</Window>
如果我运行这个,XamlParseException
会抛出一个,说flatButtonStyle
找不到静态资源。
我发现的唯一解决方法是将公共资源字典显式合并到控件模板的本地资源字典中:
<ControlTemplate TargetType="local:MyControl">
<ControlTemplate.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/AppWideResources;component/CommonResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ControlTemplate.Resources>
<StackPanel Orientation="Horizontal">
<Button Style="{StaticResource flatButtonStyle}" Content="1"/>
<Button Style="{StaticResource flatButtonStyle}" Content="2"/>
</StackPanel>
</ControlTemplate>
然而,这不仅非常冗长且容易出错,有几行冗余代码(我的实际项目包含相当多的模板控件,而不仅仅是一个),我还担心通过多次加载静态资源而浪费系统资源(包括每次一次CommonResources.xaml
)。(这种担心是否合理?或者 WPF 每次加载特定资源字典时是否使用相同的实例?)
因此,问题是:使 WPF 资源在整个应用程序(包括控件模板)中可访问的正确方法是什么?