Проблема с общими ресурсами WinForms между проектами в Visual Studio - PullRequest
11 голосов
/ 09 июля 2009

Я переместил все ресурсы изображений в большом многопроектном решении в новый проект, специально созданный для общих ресурсов.

Добавление новой ссылки на другие проекты, в которых используются общие изображения, работает должным образом. Изображение в выбранной кнопке ниже продолжает появляться в конструкторе, но с проблемами.

В VS Designer я не могу выбрать общие ресурсы в редакторе изображений, вместо этого приходится вручную редактировать код дизайнера.

В частности, в диалоговом окне «Редактор изображений» (доступ к которому осуществляется из свойства «Изображение» существующего элемента управления) я выбираю «Выбрать из файла / ресурса ...», чтобы открыть диалоговое окно «Выбор ресурса» (показано). Там, где Я использовал для доступа ко всем локальным ресурсам проекта (Resources.resx), теперь я хотел бы добавить доступ к новому проекту общих ресурсов. В идеале, я бы добавил второй элемент в раскрывающемся списке, который переключается на resx для проекта общих ресурсов. .

Как это можно сделать? Есть ли лучший способ?

alt text

Ответы [ 5 ]

20 голосов
/ 07 июня 2011

Я смог поделиться файлом resx между проектами и использовать его в конструкторе в VS 2008 SP1 (не знаю других версиях). В отличие от других подходов, здесь ресурсы статически и динамически совместно используются, поэтому во время выполнения действительно существует одна копия общих ресурсов. Никаких потерь памяти или памяти, простота обслуживания с помощью множества проектов.

Следуйте инструкциям и скажите, работает ли он для вас:

  • Создание класса ресурсов проекта;
  • Создать файл ресурсов (зайдите в Свойства -> Ресурсы проекта);
  • Переместить файл ресурсов (по умолчанию Resources.resx) в root проекта;
  • Переименование файла ресурсов Resources.resx -> GlobalResources.resx;
  • Изменить модификатор файла ресурсов на Public (двойной щелчок по файлу ресурсов, «Access Modifier» -> «Public»);
  • Скопируйте любой файл ресурса в корневой каталог проекта;
  • Добавьте любой ресурс в файл ресурсов, используя «Добавить существующий файл» и выбрав ресурсы в каталоге root проекта.

Проект в обозревателе решений должен выглядеть следующим образом:

enter image description here

Теперь в любом проекте вам нужен общий файл 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>
    

Очевидно, что атрибут «Включить» должен быть правильным относительным путем к GlobalResources.resx.

  • Используйте ресурсы в конструкторе, как вы и просили.

В моем проекте следующие строки генерируются и добавляются в проект автоматически, когда я делаю это:

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

Если они не добавлены, добавьте их вручную.

Теперь проект должен выглядеть следующим образом в обозревателе решений (сходные файлы должны быть помечены по-другому):

enter image description here

Последние два шага:

  • Нажмите на ссылку «GlobalResources.resx» и в свойствах установите «None» в качестве «BuildAction». «Пространство имен пользовательских инструментов» уже должно быть установлено на «Ресурсы»;

enter image description here

  • Нажмите на ссылку «GlobalResources.Designer.resx» и в свойствах установите «None» как «BuildAction».

enter image description here

И все готово: к этому моменту вы действительно сможете использовать ресурсы, добавленные вами в общий ресурс в конструкторе, выбрав "GlobalResources.resx" в диалоговом окне "Файл ресурсов проекта" вашего вопроса. И, как сказано, он действительно доступен даже во время выполнения! На панели «Свойства» вы должны увидеть полное пространство имен и класс внешнего проекта. Если вы удалите зависимость от проекта «Ресурс», он даже не скомпилируется. Если это не работает для вас, настаивайте до тех пор, пока это не сработает, и в случае, скажите мне, где руководство неверно. Это должно работать! Дайте мне знать.

8 голосов
/ 31 января 2011

Я недавно столкнулся с той же проблемой. Посмотрел документацию MS, но не смог найти хороших решений. В конце концов мне удалось заставить редактор изображений в конструкторе WinForms распознавать файлы ресурсов из других проектов, используя метод, описанный ниже. Это хакерство - если у кого-то есть более чистое решение, которым он хочет поделиться, пожалуйста, напишите. Я проверял это только на VS 2008.

Прежде чем начать, я должен сказать, что если вы просто хотите сделать элементы в файле Resources.resx доступными для других проектов, вы можете просто отредактировать его свойства и установить для общего доступа модификатор доступа для сгенерированного класса, чтобы он использовал PublicResXFileCodeGenerator , Приведенная ниже гимнастика необходима только в том случае, если вы хотите, чтобы дизайнеры WinForms брали изображения внутри этого файла ресурсов, как описано в посте выше от Дугласа.

Скажите, что ваше решение имеет следующий макет. Здесь важно пространство имен по умолчанию для различных проектов (щелкните правой кнопкой мыши узел проекта в обозревателе решений -> Свойства -> вкладка «Приложение»), поэтому я поместил его в квадратные скобки после имен проектов.

  • MySolution
    • SharedProject (пространство имен по умолчанию = SharedProject)
      • SharedProject.csproj
    • WinFormsProject1 (пространство имен по умолчанию = WinFormsProject1)
      • WinFormsProject1.csproj
    • WinFormsProject2 (пространство имен по умолчанию = WinFormsProject2)
      • WinFormsProject2.csproj

Вы хотите создать файл ресурсов в SharedProject , содержащий изображения, которые могут использоваться WinFormsProject1 и WinFormsProject2 .

Сначала создайте новый файл ресурсов в корне SharedProject , назовем его SharedResources.resx . Важно, чтобы этот файл использовал ResXFileCodeGenerator, а не PublicResXFileCodeGenerator, по причинам, которые станут понятны позже.

Редактируйте SharedResources.resx в Visual Studio и добавьте ресурсы изображений, которыми вы хотите поделиться. Visual Studio также должна сгенерировать для вас файл класса внутри SharedProject с именем SharedResources.designer.cs .

Ваше решение должно выглядеть следующим образом:

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

Теперь вам нужно сделать ресурсы доступными внутри 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>

Ключевыми вещами здесь являются CustomToolNamespace и LogicalName . По умолчанию Visual Studio использует пространство имен проекта по умолчанию для именования ресурсов и создания файла * .Designer.cs. Поскольку SharedProject и WinFormsProject1 имеют разные пространства имен по умолчанию, поведение по умолчанию приводит к несовместимости ресурса, встроенного в WinFormsProject1 , с файлом * .Designer.cs, который является внутри SharedProject . Этого можно избежать, переопределив CustomToolNamespace и LogicalName.

Теперь сделайте то же самое для WinFormsProject2.csproj . Вернитесь в Visual Studio. Он заметит, что вы изменили файлы csproj и попросит перезагрузить проекты - выберите «перезагрузить». Вы должны обнаружить, что теперь вы можете выбирать изображения из SharedResources.resx при проектировании форм в WinFormsProject1 и WinFormsProject2 .

По сути, все это делает VS включающим файл SharedResources.resx из SharedProject в WinFormsProject1 и WinFormsProject2, Существует только один исходный файл .resx (в SharedProject ), но при компиляции решения на самом деле будет три идентичных класса с именем SharedProject.SharedResources , по одному в каждой из трех сборок. , но так как все имеют внутреннюю видимость, они не будут мешать друг другу, даже если вы добавите ссылку между проектами.

6 голосов
/ 06 мая 2013

ОБМЕН РЕСУРСАМИ МЕЖДУ ПРОЕКТАМИ В VS2012

в 3 простых шага с использованием только дизайнера!

  1. создайте проект и добавьте свои ресурсы для совместного использования как обычно
  2. создайте другой проект и «добавьте в качестве ссылки» resources.resx первого проекта в диалоге «добавить существующий элемент», доступный из контекстного меню
  3. выберите изображения из связанного файла ресурсов по желанию; это можно выбрать в раскрывающемся меню «файл ресурсов проекта» в диалоге «выбор ресурса», доступном из панели свойств

VOILA!

1 голос
/ 16 сентября 2012

Вам нужно только добавить новый проект класса с файлом RESX, куда вы включаете ресурсы (изображения, тексты и т. Д.). После в других проектах добавьте ссылку на это и используйте имя класса Resource для доступа к необходимому ресурсу, например: Project.SharedImages.Upload_64x64 (в результате получается растровое изображение, готовое к использованию в этом случае)

0 голосов
/ 03 августа 2017

Для Visual Studio 2015 +

Существует простой, простой способ, который не поддерживается в пользовательском интерфейсе VisualStudio. Так что, если вы не боитесь редактировать файлы проекта, читайте дальше.

Если вы еще этого не сделали, добавьте в решение новый общий проект. Add a New Shared Projecct

Если вы еще этого не сделали, включите новый общий проект в качестве ссылки на общий проект для своего периферийного проекта. enter image description here

Обратите внимание, как этот общий проект включается в периферийный проект (файл .csproj) прямым способом:

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

Таким образом, даже несмотря на то, что пользовательский интерфейс VS не предоставляет его, все в общем проекте (файл .projitems) включается непосредственно в периферийный проект. Добавление следующих определений ресурсов в общий проект (файл .projitems) включит их непосредственно в периферийный проект. Но поскольку элемент Resource не поддерживается пользовательским интерфейсом VS для общих проектов, эти файлы будут скрыты и проигнорированы в 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"), эти ресурсы компилируются в ваш периферийный проект с базовыми идентификаторами, а не абсолютными или относительными. e.g.:

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