【发布时间】:2014-01-16 10:23:33
【问题描述】:
我正在寻找一种方法来定义可从我的应用程序中的任何位置访问的 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>
this question 的选定答案表明我必须将该资源字典合并到我的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 资源在整个应用程序(包括控件模板)中可访问的正确方法是什么?
【问题讨论】:
-
提供的答案是否不够好?
-
@RohitVats: 耐心 ;-) 我已经看到你的回答并且它有效,我可能会接受它;我只是倾向于将问题留待一天左右,以防其他人提出更好的解决方案。
标签: wpf resources controltemplate staticresource app.xaml