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

Visual Studio中跨项目共享WinForms资源的问题,winforms,visual-studio-designer,Winforms,Visual Studio Designer,我已将大型多项目解决方案中的所有图像资源移动到专门为共享资源创建的新项目中 将新引用添加到使用共享映像的其他项目中,工作正常。下面所选按钮中的图像继续显示在designer中,但存在问题 在VS Designer中,我无法在图像编辑器中选择共享资源,而必须手动编辑设计器代码 更具体地说,在“图像编辑器”对话框(从现有控件的“图像”属性访问)中,我选择“从文件/资源中选择…”以弹出“选择资源”对话框(如图所示)。在该对话框中,我用于访问所有本地项目资源(resources.resx),我现在想添加

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

将新引用添加到使用共享映像的其他项目中,工作正常。下面所选按钮中的图像继续显示在designer中,但存在问题

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

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

如何做到这一点?有更好的方法吗


我最近遇到了同样的问题。查阅了MS文档,但找不到任何好的解决方案。我最终能够让WinForms designer中的图像编辑器使用下面描述的方法识别来自其他项目的资源文件。这是一种黑客行为-如果有人想要共享更干净的解决方案,请我只在VS 2008上测试过这个

在我开始之前,我应该说,如果您只想让Resources.resx文件中的项目可供其他项目访问,您可以编辑其属性并将生成的类的访问修饰符设置为public,以便它使用PublicResXFileCodeGenerator。只有当您想让WinForms设计人员选择u时,才需要下面的练习p这个资源文件中的图像,如上面Douglas的文章所述

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

  • 我的解决方案
    • SharedProject(默认命名空间=SharedProject)
      • SharedProject.csproj
    • WinFormsProject1(默认命名空间=WinFormsProject1)
      • WinFormsProject1.csproj
    • WinFormsProject2(默认命名空间=WinFormsProject2)
      • WinFormsProject2.csproj
您希望在SharedProject中创建一个资源文件,其中包含WinFormsProject 1和WinFormsProject 2可以使用的映像

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

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

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

  • 我的解决方案
    • SharedProject(默认命名空间=SharedProject)
      • SharedProject.csproj
      • SharedResources.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>

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

打开WinFormsProject1.csproj文件,并在项目组中添加以下内容:

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

SharedResources.Designer.cs
真的
真的
SharedResources.resx
SharedResources.resx
ResXFileCodeGenerator
SharedResources.Designer.cs
共享项目
SharedProject.SharedResources.resources
这里的关键内容是CustomToolNamespaceLogicalName。默认情况下,Visual Studio使用项目的默认名称空间命名资源并生成*.Designer.cs文件。由于SharedProject和WinFormsProject1具有不同的默认名称空间,因此默认行为会导致嵌入资源WinFormsProject1中的“”被重写为与SharedProject中的*.Designer.cs文件不兼容。可以通过重写CustomToolNamespace和LogicalName来防止此问题

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


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

我能够在项目和使用之间共享resx文件与其他方法不同,这里的资源是静态和动态共享的,因此在运行时实际上只有一个共享资源的副本
 <ItemGroup>
   ...
   <EmbeddedResource Include="..\Resources\GlobalResources.resx">
     <Link>GlobalResources.resx</Link>
     <Generator>ResXFileCodeGenerator</Generator>
     <LastGenOutput>GlobalResources.Designer.cs</LastGenOutput>
     <CustomToolNamespace>Resources</CustomToolNamespace>
   </EmbeddedResource>
   ...
 </ItemGroup>
<Compile Include="..\Resources\GlobalResources.Designer.cs">
  <Link>GlobalResources.Designer.cs</Link>
  <AutoGen>True</AutoGen>
  <DesignTime>True</DesignTime>
  <DependentUpon>GlobalResources.resx</DependentUpon>
</Compile>
<Import Project="..\Common\Common.projitems" Label="Shared" />
<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>
<Window x:Class="Common.Shared"
  ...
  Icon="one.ico">
  <Window.Resources>
    <ResourceDictionary>
      <BitmapImage x:Key="one64" UriSource="one 64x64.png"/>
    </ResourceDictionary>
  </Window.Resources>
<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>