15

我已将大型多项目解决方案中的所有图像资源移动到专门为共享资源创建的新项目中。

添加对使用共享图像的其他项目的新引用按预期工作。下面所选按钮中的图像继续出现在设计器中,但存在问题。

在 VS Designer 中,我无法在图像编辑器中选择共享资源,而不得不手动编辑设计器代码。

更具体地说,在“图像编辑器”对话框(从现有控件的“图像”属性访问)中,我选择“从文件/资源​​中选择...”以弹出“选择资源”对话框(如图所示)。在那里,我曾经访问所有本地项目资源(Resources.resx),我现在想添加对新共享资源项目的访问权限。理想情况下,我会在显示的下拉列表中添加第二个项目,该项目切换到共享资源项目的 resx。

如何才能做到这一点?有没有更好的办法?

替代文字

4

6 回答 6

25

我能够在项目之间共享一个 resx 文件,并在 VS 2008 SP1 的设计器中使用它(我不知道其他版本)。与其他方法不同,这里的资源是静态和动态共享的,因此在运行时实际上只有一个共享资源的副本。没有存储或内存浪费,并且易于维护大量项目。

按照指南告诉我它是否适合您:

  • 创建类项目资源;
  • 创建一个资源文件(转到项目的属性-> 资源);
  • 将资源文件(默认 Resources.resx)移动到项目的根目录
  • 重命名资源文件Resources.resx -> GlobalResources.resx;
  • 修改资源文件修饰符为Public(双击资源文件,“Access Modifier”->“Public”);
  • 将任意资源文件复制到项目根目录下;
  • 使用“添加现有文件”并在项目的目录中选择资源,将任何资源添加到资源文件中。

解决方案资源管理器中的项目应如下所示:

在此处输入图像描述

现在在任何项目中,您都需要共享 resx 文件,请执行以下操作:

  • 添加“资源”项目作为依赖项;

  • 手动编辑项目文件 (*.csproj) 并在资源文件 ItemGroup 中添加以下行(如果要查看,请创建本地资源文件):

     <ItemGroup>
       ...
       <EmbeddedResource Include="..\Resources\GlobalResources.resx">
         <Link>GlobalResources.resx</Link>
         <Generator>ResXFileCodeGenerator</Generator>
         <LastGenOutput>GlobalResources.Designer.cs</LastGenOutput>
         <CustomToolNamespace>Resources</CustomToolNamespace>
       </EmbeddedResource>
       ...
     </ItemGroup>
    

显然,“Include”属性应该是 GlobalResources.resx 的正确相对路径。

  • 按照您的要求使用设计器中的资源。

在我的项目中,执行此操作时会自动生成以下行并将其添加到项目中:

<Compile Include="..\Resources\GlobalResources.Designer.cs">
  <Link>GlobalResources.Designer.cs</Link>
  <AutoGen>True</AutoGen>
  <DesignTime>True</DesignTime>
  <DependentUpon>GlobalResources.resx</DependentUpon>
</Compile>

如果未添加,请手动添加。

现在项目在解决方案资源管理器中应该看起来像这样(likend 文件应该有不同的标记):

在此处输入图像描述

最后两步:

  • 单击链接的“GlobalResources.resx”并在“属性”上将“无”设置为“BuildAction”。“自定义工具命名空间”应该已经设置为“资源”;

在此处输入图像描述

  • 单击链接的“GlobalResources.Designer.resx”并在“属性”上将“无”设置为“BuildAction”。

在此处输入图像描述

你就完成了:此时你应该真的能够在设计器中使用你在共享 resx 中添加的资源,在你的问题的“项目资源文件”对话框中选择“GlobalResources.resx”。正如所说,即使在运行时它也确实是共享的!在“属性”面板中,您应该会看到外部项目的完整命名空间和类。如果您删除对“资源”项目的依赖,它甚至不会编译。如果它对你不起作用,坚持直到它起作用,以防告诉我指南哪里错了。它必须工作!让我知道。

于 2011-06-07T19:24:27.893 回答
9

我最近遇到了同样的问题。查看了 MS 文档,但找不到任何好的解决方案。我最终能够使用下面描述的方法让 WinForms 设计器中的图像编辑器识别来自其​​他项目的资源文件。这很 hacky - 如果有人想分享更清洁的解决方案,请发布。我仅在 VS 2008 上对此进行了测试。

在开始之前,我应该说,如果您只是想让 Resources.resx 文件中的项目可供其他项目访问,您只需编辑其属性并将生成的类的访问修饰符设置为 public,以便它使用 PublicResXFileCodeGenerator。仅当您想让 WinForms 设计人员按照上述 Douglas 的帖子中所述在此资源文件中拾取图像时,才需要下面的操作。

假设您的解决方案具有以下布局。各种项目的默认命名空间(在解决方案资源管理器中右键单击项目节点 -> 属性 -> 应用程序选项卡)在这里很重要,因此我将其放在项目名称后面的括号中。

  • 我的解决方案
    • SharedProject(默认命名空间 = SharedProject)
      • SharedProject.csproj
    • WinFormsProject1(默认命名空间 = WinFormsProject1)
      • WinFormsProject1.csproj
    • WinFormsProject2(默认命名空间 = WinFormsProject2)
      • WinFormsProject2.csproj

您想在SharedProject中创建一个资源文件,其中包含WinFormsProject1WinFormsProject2可以使用的图像。

首先在SharedProject的根目录下新建一个 Resource 文件,我们称之为SharedResources.resx。此文件使用 ResXFileCodeGenerator 而不是 PublicResXFileCodeGenerator 很重要,原因稍后会清楚。

在 Visual Studio 中编辑SharedResources.resx并添加要共享的图像资源。Visual Studio 还应该在SharedProject中为您生成一个名为SharedResources.designer.cs的类文件。

您的解决方案现在应该如下所示:

  • 我的解决方案
    • SharedProject(默认命名空间 = SharedProject)
      • SharedProject.csproj
      • 共享资源.resx
      • SharedResources.Designer.cs
    • WinFormsProject1(默认命名空间 = WinFormsProject1)
      • WinFormsProject1.csproj
    • WinFormsProject2(默认命名空间 = WinFormsProject2)
      • WinFormsProject2.csproj

如果您使用文本编辑器打开SharedProject.csproj,您应该会看到以下条目:

<EmbeddedResource Include="SharedResources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>SharedResources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Include="SharedResources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>SharedResources.resx</DependentUpon>
</Compile>

现在您需要使 WinFormsProject1 中的资源可访问。为此,您需要在文本编辑器中编辑WinFormsProject1.csproj,因为您需要设置的某些属性未在 Visual Studio 中公开。

打开WinFormsProject1.csproj文件并在 ItemGroup 中添加以下内容:

<Compile Include="..\SharedProject\SharedResources.Designer.cs">
    <Link>SharedResources.Designer.cs</Link>
    <AutoGen>True</AutoGen>
    <DesignTime>True</DesignTime>
    <DependentUpon>SharedResources.resx</DependentUpon>
</Compile>
<EmbeddedResource Include="..\SharedProject\SharedResources.resx">
    <Link>SharedResources.resx</Link>
    <Generator>ResXFileCodeGenerator</Generator>
    <LastGenOutput>SharedResources.Designer.cs</LastGenOutput>
    <CustomToolNamespace>SharedProject</CustomToolNamespace>
    <LogicalName>SharedProject.SharedResources.resources</LogicalName>
</EmbeddedResource>

这里的关键是CustomToolNamespaceLogicalName。默认情况下,Visual Studio 使用项目的默认命名空间来命名资源并生成 *.Designer.cs 文件。由于SharedProjectWinFormsProject1具有不同的默认命名空间,默认行为会导致WinFormsProject1中嵌入的资源与SharedProject中的 *.Designer.cs 文件不兼容。这可以通过覆盖 CustomToolNamespace 和 LogicalName 来防止。

现在对WinFormsProject2.csproj做同样的事情。返回到 Visual Studio。它会注意到您已更改 csproj 文件并要求重新加载项目 - 选择“重新加载”。您应该会发现,在WinFormsProject1WinFormsProject2中设计表单时,您现在可以从SharedResources.resx中选择图像。

本质上,所有这一切都是使 VS在WinFormsProject1WinFormsProject2项目中包含来自SharedProject的SharedResources.resx文件。只有一个 .resx 源文件(在SharedProject中),但是当您编译解决方案时,实际上会有三个相同的类,称为SharedProject.SharedResources,三个程序集中各有一个,但由于它们都具有内部可见性,因此它们不会干扰即使您在项目之间添加引用,也可以相互关联。

于 2011-01-30T22:29:52.237 回答
7

VS2012项目间资源共享

只需使用设计器,只需 3 个简单的步骤!

  1. 创建一个项目并像往常一样添加要共享的资源
  2. 创建另一个项目并在“添加现有项目”对话框中“添加为链接”第一个项目的 resources.resx,可从上下文菜单访问
  3. 根据需要从链接的资源文件中选择图像;这可以在“选择资源”对话框中的“项目资源文件”下拉菜单中选择,可从属性窗格访问

瞧!

于 2013-05-06T06:19:36.717 回答
2

对于 Visual Studio 2015+

VisualStudio UI 不支持一种简单直接的方法。因此,如果您不害怕编辑项目文件,请继续阅读。

如果您尚未这样做,请将新的共享项目添加到解决方案中。添加新的共享项目

如果您还没有这样做,请将新的共享项目作为共享项目引用包含在您的外围项目中。在此处输入图像描述

请注意此共享项目如何.csproj以直接的方式包含在外围项目(文件)中:

<Import Project="..\Common\Common.projitems" Label="Shared" />

因此,即使 VS UI 没有公开它,共享项目(.projitems文件)中的所有内容都直接包含在外围项目中。将以下资源定义添加到共享项目(.projitems文件)中会将它们直接包含到您的外围项目中。但是,因为Resource共享项目的 VS UI 不支持该元素,所以这些文件将在 IDE 中被隐藏和忽略。

<ItemGroup>
  <Resource Include="$(MSBuildThisFileDirectory)Resources\one 16x16.png" />
  <Resource Include="$(MSBuildThisFileDirectory)Resources\one 64x64.png" />
  <Resource Include="$(MSBuildThisFileDirectory)Resources\one.ico" />
  <Resource Include="$(MSBuildThisFileDirectory)Resources\two 16x16.png" />
  <Resource Include="$(MSBuildThisFileDirectory)Resources\three 16x16.png" />
  <Resource Include="$(MSBuildThisFileDirectory)Resources\four 16x16.png" />
  <Resource Include="$(MSBuildThisFileDirectory)Resources\five 16x16.png" />
  <Resource Include="$(MSBuildThisFileDirectory)Resources\six 16x16.png" />
</ItemGroup>

最后,虽然您的外围项目资源可能具有相对路径(例如".\Resources\main.ico"),但这些资源会以基本 id 而非绝对或相对的方式编译到外围项目中。例如:

<Window x:Class="Common.Shared"
  ...
  Icon="one.ico">
  <Window.Resources>
    <ResourceDictionary>
      <BitmapImage x:Key="one64" UriSource="one 64x64.png"/>
    </ResourceDictionary>
  </Window.Resources>
于 2017-08-02T21:27:22.510 回答
1

您只需添加一个包含资源(图像、文本等)的 RESX 文件的新类项目。在其他项目中添加对此的引用并使用 Resource 类名称以访问所需的资源,例如:Project.SharedImages.Upload_64x64(结果是在这种情况下可以使用的位图)

于 2012-09-16T00:50:14.213 回答
0

查理的回答效果很好!

只是一个小改动:如果您想跳过最后两个步骤,请在修改项目文件时使用此版本的包含项。

<None Include="..\Resources\GlobalResources.resx">
      <Link>GlobalResources.resx</Link>
      <Generator>PublicResXFileCodeGenerator</Generator>
      <LastGenOutput>GlobalResources.Designer.cs</LastGenOutput>
      <CustomToolNamespace>Resources</CustomToolNamespace>
</None>
<None Include="..\Resources\GlobalResources.Designer.cs">
      <Link>GlobalResources.Designer.cs</Link>
      <DependentUpon>GlobalResources.resx</DependentUpon>
</None>
于 2021-01-01T20:48:37.957 回答