将 ResourceDictionary 添加到类库
Posted
技术标签:
【中文标题】将 ResourceDictionary 添加到类库【英文标题】:Add ResourceDictionary to class library 【发布时间】:2011-12-31 16:44:40 【问题描述】:我创建了一个类库,其中包含 WPF Windows 和一些从我的 c# 类继承的用户控件,可帮助我自定义某些 wpf 控件。
现在我想添加 ResourceDictionary,以帮助我在我的 wpf 类之间共享样式。有可能吗?
谢谢。
编辑: 位于 MY.WpfPresentation.Main 项目中的资源字典文件(名为 Styles.xaml):
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:dxgt="http://schemas.devexpress.com/winfx/2008/xaml/grid/themekeys"
xmlns:MYNetMisc="clr-namespace:MY.Net.Misc;assembly=MY.Net"
>
<Style x:Key="customRowStyle" BasedOn="StaticResource dxgt:GridRowThemeKey ResourceKey=RowStyle" TargetType="x:Type dxg:GridRowContent">
<Setter Property="Foreground" Value="Binding Path=DataContext.balance, Converter=MYNetMisc:BalanceToColor OnlyNegative=false" />
</Style>
</ResourceDictionary>
使用它:
<MYNetPresentation:frmDockBase.Resources>
<ResourceDictionary x:Key="style">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MY.WpfPresentation.Main;component/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
<DataTemplate x:Key="TabTemplate">
<dxlc:LayoutControl Padding="0" ScrollBars="None" Background="Transparent">
<Image Source="/Images/Icons/table-32x32.png" Width="12" Height="12" />
<TextBlock Text="Binding" HorizontalAlignment="Left" VerticalAlignment="Center" />
</dxlc:LayoutControl>
</DataTemplate>
</MYNetPresentation:frmDockBase.Resources>
【问题讨论】:
【参考方案1】:创建一个像这样的资源字典
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Common base theme -->
<ResourceDictionary Source="pack://application:,,,/Another.AssemblyName;component/YourResDictionaryFolder/OtherStyles.xaml" />
<ResourceDictionary Source="pack://application:,,,/Another.AssemblyName;component/YourResDictionaryFolder/AnotherStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
<!-- store here your styles -->
</ResourceDictionary>
你可以把它放在你想要的地方
<Window x:Class="DragMoveForms.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2"
Height="300"
Width="300">
<Window.Resources>
<ResourceDictionary Source="pack://application:,,,/Your.Base.AssemblyName;component/YourResDictionaryFolder/Dictionary1.xaml" />
</Window.Resources>
<Grid>
</Grid>
</Window>
【讨论】:
好吧,问题是当我尝试向项目添加新项目时,我没有看到 ResourceDictionary。 如果您的解决方案是 wpf 解决方案 -> 在解决方案资源管理器中的项目名称处鼠标右键 -> 添加 -> 资源字典,或者您可以添加一个名为 YourName.xaml 的空文件并将 ResourceDictionary 标记放入它 只有当我的项目是 WPF 应用程序时,我才能在 Add->... 上看到 ResourceDictionary。因此,我创建了新文件并将其命名为 Styles.xaml,但现在我收到异常:'Resources' 属性已设置在 啊,你必须把你的datatemplate移到resourcedictionary标签里,看看你的第一篇文章 很好的答案,但需要注意的是:不要在 pack:// uris 中的程序集名称中包含 .dll 扩展名。否则,您将花费大量时间试图了解它为什么不起作用【参考方案2】:要将经典库项目转换为 WPF 库项目(以添加 UserControls
、Windows
、ResourcesDictionaries
等),您可以在第一个 PropertyGroup 节点的 .csproj 文件中添加以下 XML :
<ProjectTypeGuids>60dc8134-eba5-43b8-bcc9-bb4bc16c2548;FAE04EC0-301F-11D3-BF4B-00C04F79EFBC</ProjectTypeGuids>
完整示例:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>50E8AAEA-5CED-46BE-AC9A-B7EEF9F5D4C9</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>WpfApplication2</RootNamespace>
<AssemblyName>WpfApplication2</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>60dc8134-eba5-43b8-bcc9-bb4bc16c2548;FAE04EC0-301F-11D3-BF4B-00C04F79EFBC</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<!-- ... -->
【讨论】:
【参考方案3】:@punker76 的answer 很棒,对我帮助很大,但值得补充的是,如果您创建一个空文件并在其中添加资源标签,您还应该转到文件属性,设置 BuildAction 到 Resource,复制到... 到 不复制 并清除已设置的 CustomTool 属性。
【讨论】:
【参考方案4】:在我看来,问题在于将 WPF 资源字典文件添加到类库项目中。答案是经典的类库不能这样做,但是对于WPF应用程序项目、WPF自定义控件库项目或者WPF 用户控件库。对于这些项目类型,您可以添加一个新的资源字典 (WPF),该选项可通过向项目添加新项目来获得。
在我看来,实际的问题标题和问题本身与接受的答案并不相符。
【讨论】:
【参考方案5】:如果在尝试创建字典时找不到 资源字典 (WPF) 文件类型,请执行以下操作:
将以下行添加到您的项目文件 (.csproj) 的第一个 <PropertyGroup>
元素中:
<ProjectTypeGuids>60dc8134-eba5-43b8-bcc9-bb4bc16c2548;FAE04EC0-301F-11D3-BF4B-00C04F79EFBC</ProjectTypeGuids>
重新加载项目。现在您应该拥有在普通 WPF 项目中可以找到的所有项目类型,包括资源字典 (WPF)。
【讨论】:
【参考方案6】:是的。您可以将 ResourceDictionary 直接添加到您的项目中。
当您想使用它时,您可以根据需要将其合并到 XAML 中,方法是使用 MergedDictionaries 将独立的 ResourceDictionary
“合并”到该类型的资源(即:Window 或 UserControl)中。
【讨论】:
【参考方案7】:由于我还不能发表评论,但我现在已经使用了两次这个答案:
补充 nmariot 的答案:
提示 1
从 Visual Studio 访问 .csproj 文件
右键项目->点击“卸载项目”
右键单击项目[处于卸载状态]->单击'编辑'filename.csproj''
提示 2
为了避免在添加资源字典后出现错误警告:
添加对 System.Xaml 的引用
【讨论】:
【参考方案8】:我刚刚在一个以前是 Windows 应用程序的项目中遇到了同样的问题,然后我变成了一个类库(我删除了默认的 App.xaml)。我尝试了上面的所有答案,并设法让我的 Visual Studio 让我从解决方案资源管理器创建一个资源字典。就我而言,我的 WPF UI 是从另一个启动的,所以我使用了Application.Run(myMainWindow)
。
到目前为止一切顺利。但后来我发现,由于资源字典没有通过 App.xaml 添加到资源层次结构的顶部,我不得不在数百个 .xaml 文件中添加对 resourceDictionary 的引用(或者至少我不能使用 xaml 使其以任何其他方式工作)。因此,我为我的案例找到了一种解决方法,使用可能对某人有所帮助的代码。
这个想法只是将 ResourceDictionary 转换为完整的类,如 here 或 here 中所述,然后在使用任何 xaml 之前的代码中强制将 RD 的实例添加到资源层次结构的顶部创建这些资源,模拟 App.xaml 会做的事情。这样,应用程序中的所有以下 WPF 都将继承这些样式,并且不需要进一步的引用。
它的优点是,如果您更改 resourceDictionary 的位置,则不必更改所有路径(尽管如果您将 RD 称为 @ 中的完整类,则您也不必这样做987654323@)。
但是如果您直接使用Application.Run(myMainWindow)
,资源不会在版本时解析,这很烦人,所以我通过启动一个派生自 Application 的类以及关联的 xaml 并引用来解决它那里的 RD 也是如此(就像默认的 App.xaml 一样)。 请注意,对 RD 的两个引用都是必需的,一个用于运行时,另一个用于编辑时。
App.xaml 看起来像:
<!-- App.xaml emulation-->
<Application x:Class="myNamespace.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-myNamespace">
<Application.Resources>
<ResourceDictionary >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
和
//App.xaml.cs
using System.Windows;
namespace myNamespace
public partial class App : Application
protected override void OnStartup(StartupEventArgs e)
//Custom startup code here
base.OnStartup(e);
和 ResourceDictionary 类似:
<!-- MyStyles.xaml -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:myNamespace"
x:Class="myNamespace.MyStyles"
x:ClassModifier="public">
<!-- All my styles in here -->
</ResourceDictionary>
和
//MyStyles.xaml.cs
using System.Windows;
namespace myNamespace
public partial class MyStyles: ResourceDictionary
public MyStyles()
InitializeComponent();
最后启动 GUI:
public static void LaunchMainWindow()
App app = new App();
//This sets the ResourceDict at the top of the hierarchy
app.Resources.MergedDictionaries.Add(new MyStyles());
app.Run(new myMainWindow());
【讨论】:
以上是关于将 ResourceDictionary 添加到类库的主要内容,如果未能解决你的问题,请参考以下文章
WPF 添加 Resources Dictionary 资源 一般类库项目中无法添加资源文件(ResourceDictionary)