将ResourceDictionary添加到类库中

29
我创建了一个类库,其中包含了一些继承自我的C#类的WPF窗口和一些用户控件,它们帮助我定制特定的WPF控件。
现在我想添加ResourceDictionary来帮助我在我的WPF类之间共享样式。这可能吗?
谢谢。
编辑: ResourceDictionary文件位于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>
8个回答

34

创建一个类似于这样的资源字典

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

2
问题在于,当我尝试向项目添加新项时,我看不到ResourceDictionary。 - davor
1
如果您的解决方案是 WPF 解决方案 -> 在解决方案资源管理器中右键单击项目名称 -> 添加 -> 资源字典,或者您可以添加一个名为 YourName.xaml 的空文件,并在其中放置 ResourceDictionary 标记。 - punker76
只有当我的项目是WPF应用程序时,我才能在Add->...上看到ResourceDictionary。因此,我创建了一个名为Styles.xaml的新文件,但现在我收到了异常:“'Resources'属性已经在上设置了。” - davor
啊,你必须将你的DataTemplate移动到ResourceDictionary标签中,在你的第一篇帖子中查看。 - punker76
1
很好的答案,但需要注意:在pack:// URI中的程序集名称中不要包含.dll扩展名。否则,您将花费大量时间尝试理解为什么它不起作用。 - Marek

19
为了将一个经典的库项目转换为WPF库项目(以添加UserControls、Windows、ResourcesDictionaries等),您可以在.csproj文件的第一个PropertyGroup节点中添加以下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>
    <!-- ... -->    

17

@punker76的答案很好,帮了我很多忙,但值得注意的是,如果您创建一个空文件并在其中添加资源标签,则还应该转到文件属性,将BuildAction设置为ResourceCopy To...设置为Do not copy,如果已设置,则清除CustomTool属性。


13

我认为这个问题是关于如何将一个WPF资源字典文件添加到一个类库项目中。答案是你不能在经典的类库中这样做,但可以在WPF应用程序WPF自定义控件库WPF用户控件库等项目类型中添加新的资源字典(WPF),这个选项可以通过向项目添加新项来获取。

我认为实际的问题标题和问题本身与已接受的答案不相符。


5
如果您在创建字典时找不到 Resource Dictionary (WPF) 文件类型,请按照以下步骤操作:
将以下行添加到项目文件(.csproj)的第一个 <PropertyGroup> 元素中:
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

重新加载该项目。现在您应该拥有一个正常的WPF项目中可以找到的所有项类型,包括 资源字典(WPF)


1

我还不能发表评论,但我已经两次使用了这个答案:

补充nmariot的答案:


技巧1

从Visual Studio访问.csproj文件的方法:

右键单击项目 -> 单击“卸载项目”

右键单击已卸载的项目 -> 单击“编辑 'filename.csproj'”

技巧2

在添加资源字典后避免错误警告的方法:

添加对System.Xaml的引用


1

可以。您可以直接将ResourceDictionary添加到项目中。

当您想要使用它时,可以使用MergedDictionaries将其合并到XAML中,以便将独立的ResourceDictionary“合并”到类型(即窗口或用户控件)的资源中。


0

我在一个之前是Windows应用程序的项目中遇到了同样的问题,然后我将其转换为类库(其中删除了默认的App.xaml)。我尝试了上面所有的答案,并成功让我的Visual Studio允许我从解决方案资源管理器中创建资源字典。在我的情况下,我的WPF UI是从另一个UI启动的,所以我使用了Application.Run(myMainWindow)

到目前为止一切都很好。但是我发现,由于资源字典没有通过App.xaml添加到资源层次结构的顶部,我不得不在数百个.xaml文件中添加对resourceDictionary的引用(或者至少我无法使用xaml以其他方式使其工作)。因此,我找到了一个使用代码后台的解决方法,可能会帮助某些人。

这个想法就是将ResourceDictionary转换为一个完整的类,如此处此处所解释的那样,然后在代码后台中强制将RD的实例添加到资源层次结构的顶部,在创建使用这些资源的任何xaml之前,模拟App.xaml所做的操作。这样,应用程序中的所有后续WPF都将继承这些样式,不需要进一步的引用。

它的优点是,如果您更改ResourceDictionary的位置,则不必更改所有路径(尽管如果您像此处中引用RD作为完整类,也不必这样做)。

但是,如果您直接使用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());
        }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接