将 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 库项目(以添加 UserControlsWindowsResourcesDictionaries 等),您可以在第一个 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 很棒,对我帮助很大,但值得补充的是,如果您创建一个空文件并在其中添加资源标签,您还应该转到文件属性,设置 BuildActionResource复制到...不复制 并清除已设置的 CustomTool 属性。

【讨论】:

【参考方案4】:

在我看来,问题在于将 WPF 资源字典文件添加到类库项目中。答案是经典的类库不能这样做,但是对于WPF应用程序项目、WPF自定义控件库项目或者WPF 用户控件库。对于这些项目类型,您可以添加一个新的资源字典 (WPF),该选项可通过向项目添加新项目来获得。

在我看来,实际的问题标题和问题本身与接受的答案并不相符。

【讨论】:

【参考方案5】:

如果在尝试创建字典时找不到 资源字典 (WPF) 文件类型,请执行以下操作:

将以下行添加到您的项目文件 (.csproj) 的第一个 &lt;PropertyGroup&gt; 元素中:

<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)

WPF ResourceDictionary 主题资源替换

将脚手架项目添加到类库

如何将 PropertyDescriptors 添加到类而不是覆盖它们?

尝试快速将协议添加到类签名中

使用装饰器动态地将方法添加到类中