Visual Studio中跨项目共享WinForms资源的问题

xdnvmnnf  于 2023-05-18  发布在  其他
关注(0)|答案(7)|浏览(275)

我已经将一个大型多项目解决方案中的所有图像资源移动到了一个专门为共享资源创建的新项目中。
将新引用添加到使用共享映像的其他项目中,正按预期工作。下面选定按钮中的图像继续显示在设计器中,但存在问题。
在VS设计器中,我无法在图像编辑器中选择共享资源,而不得不手动编辑设计器代码。
更具体地说,在图像编辑器对话框(从现有控件的“图像”属性访问)中,我选择“从文件/资源...”弹出“选择资源”对话框(如图所示)。在那里,我曾经访问所有本地项目资源(Resources.resx),现在我想添加对新共享资源项目的访问。理想情况下,我会在所示的下拉列表中添加第二个项目,该项目切换到共享资源项目的resx。
如何才能做到这一点?有更好的办法吗?

hyrbngr7

hyrbngr71#

我能够在项目之间共享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文件应该有不同的标记):

最后两步:

  • 单击链接的“GlobalRess.resx”并将属性设置为“None”作为“BuildAction”。“自定义工具命名空间”应已设置为“资源”;

  • 单击链接的“GlobalResources.Designer.resx”,并将属性设置为“None”作为“BuildAction”。

然后你就完成了:在这一点上,你应该真的能够使用你在设计器的共享resx中添加的资源,在你的问题的“项目资源文件”对话框中选择“GlobalResource.resx”。正如所述,它甚至在运行时也是共享的!在Properties面板中,您应该看到外部项目的完整名称空间和类。如果你删除了对“Resource”项目的依赖,它甚至不会编译。如果它不适合你,坚持直到它工作,以防万一告诉我指南哪里错了。一定要成功!告诉我

6yjfywim

6yjfywim2#

我最近遇到了同样的问题。查看了MS文档,但找不到任何好的解决方案。我最终能够让WinForms设计器中的图像编辑器使用下面描述的方法识别来自其他项目的资源文件。这是黑客-如果有人有一个更干净的解决方案,他们想分享请张贴。我只在VS 2008上测试过。
在开始之前,我应该说,如果您只是想让Resources.resx文件中的项对其他项目是可访问的,那么您只需编辑它的属性,并将生成的类的访问修饰符设置为public,这样它就可以使用PublicResXFileCodeGenerator了。只有当你想让WinForms的设计者在这个资源文件中拾取图像时,下面的体操才是必需的,正如上面道格拉斯的文章中所描述的那样。
假设您的解决方案具有以下布局。各个项目的默认名称空间(右键单击solutionExplorer-> Properties -> Application选项卡中的项目节点)在这里很重要,所以我把它放在项目名称后面的方括号中。

  • MySolution
  • SharedProject(默认命名空间= SharedProject)
  • SharedProject.csproj
  • WinFormsProject 1(默认命名空间= WinFormsProject 1)
  • WinFormsProject1.csproj
  • WinFormsProject 2(默认命名空间= WinFormsProject 2)
  • WinFormsProject2.csproj

您希望在 SharedProject 中创建一个资源文件,该文件包含可由 * WinFormsProject 1 * 和 * WinFormsProject 2 * 使用的图像。
首先在 SharedProject 的根目录中创建一个新的Resource文件,我们将其命名为 SharedResources.resx。重要的是,此文件使用ResXFileCodeGenerator而不是PublicResXFileCodeGenerator,其原因将在稍后解释。
在Visual Studio中编辑 SharedResources.resx 并添加您想要共享的图像资源。VisualStudio还应该在 SharedProject 中为您生成一个名为 * SharedResources.designer.cs * 的类文件。
您的解决方案现在应该如下所示:

  • MySolution
  • SharedProject(默认命名空间= SharedProject)
  • SharedProject.csproj
    **SharedResources.resx
    *SharedResources.Designer.cs
  • WinFormsProject 1(默认命名空间= WinFormsProject 1)
  • WinFormsProject1.csproj
  • WinFormsProject 2(默认命名空间= WinFormsProject 2)
  • 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>

现在,您需要在WinFormsProject 1中访问这些资源。为此,您需要在文本编辑器中编辑 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。默认情况下,VisualStudio使用项目的默认命名空间来命名资源并生成 *.Designer.cs文件。由于 SharedProject 和 * WinFormsProject 1 * 具有不同的默认命名空间,因此默认行为会导致 * WinFormsProject 1 * 中嵌入的资源与 SharedProject 中的 *.Designer.cs文件不兼容。这可以通过重写CustomToolNamespace和LogicalName来防止。
现在对 WinFormsProject2.csproj 执行同样的操作。返回到Visual Studio。它会注意到您已经更改了csproj文件并要求重新加载项目-选择“reload”。您应该会发现,在 * WinFormsProject 1 * 和 * WinFormsProject 2 * 中设计表单时,现在可以从 SharedResources.resx 中选择图像。
从本质上讲,所有这些都是让VS在 * WinFormsProject 1 * 和 * WinFormsProject 2 * 项目中包含来自 SharedProjectSharedResources.resx 文件。只有一个.resx源文件(在 SharedProject 中),但是当你编译解决方案时,实际上会有三个相同的类,名为 SharedProject.SharedResources,三个程序集中各有一个,但是由于它们都具有内部可见性,即使你在项目之间添加引用,它们也不会相互干扰。

lztngnrs

lztngnrs3#

VS 2012项目资源共享

仅使用设计器,只需3个简单步骤即可!

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

ztyzrc3y

ztyzrc3y4#

Visual Studio 2015+

有一种简单、直接的方法,但VisualStudio UI不支持。因此,如果您不害怕编辑项目文件,请继续阅读。
如果您还没有这样做,请将新的共享项目添加到解决方案中。

如果尚未这样做,请将新共享项目作为共享项目引用包含到外围设备项目中。

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

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

因此,即使VS UI没有公开它,共享项目(.projitems文件)中的所有内容都直接包含在外围项目中。将以下资源定义添加到共享项目(.projitems文件)将直接将它们包含到外围设备项目中。但是,由于共享项目的VS UI不支持Resource元素,因此这些文件将在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(不是绝对ID或相对ID)编译到外围设备项目中。例如:

<Window x:Class="Common.Shared"
  ...
  Icon="one.ico">
  <Window.Resources>
    <ResourceDictionary>
      <BitmapImage x:Key="one64" UriSource="one 64x64.png"/>
    </ResourceDictionary>
  </Window.Resources>
j7dteeu8

j7dteeu85#

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

pokxtpni

pokxtpni6#

Charlie's answer工作得很好!
只是一个小小的改变:如果要跳过最后两个步骤,请在修改项目文件时使用包含项的此版本。

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

deyfvvtc7#

对于SDK Style项目使用以下方法,或者对于非SDK Style项目复制.targets文件(未测试)的内容。
1:在解决方案旁边创建以下文件。用全局资源的正确信息替换占位符。将其命名为例如“IncludeGlobalResources.targets”

<Project>
  <!--Makes it possible to select the Images of My.Custom.Namespace.MyGlobalResourceProject in your Projects WindowsForms-Designers-->
  <!--See https://stackoverflow.com/questions/1100455/issue-with-shared-winforms-resources-across-projects-in-visual-studio-->
  <ItemGroup>
    <None Include="..\My.Namespace.MyGlobalResourceProject\MyGlobalImages.resx">
      <Link>MyGlobalImages.resx</Link>
      <LastGenOutput>MyGlobalImages.Designer.cs</LastGenOutput>
      <Generator>none</Generator> <!-- Without this line you will get bugs as the referencing project will re-generate the source file with wrong namespaces -->
    </None>
  </ItemGroup>
  <ItemGroup>
    <None Include="..\My.Namespace.MyGlobalResourceProject\MyGlobalImages.Designer.cs">
      <Link>MyGlobalImages.Designer.cs</Link>
      <DependentUpon>MyGlobalImages.resx</DependentUpon>
    </None>
  </ItemGroup>
</Project>

2:转到项目文件(我有SDK样式的项目),在那里你想使用全局资源。引用创建的文件:

<Project Sdk="Microsoft.NET.Sdk">
  <Import Project="$(SolutionDir)\IncludeGlobalResources.targets" />
(...)

3:现在你可以加2。你想使用全局资源的每个项目。您也可以轻松地使用其他全局资源扩展文件。

相关问题