Я хочу переместить свои ресурсы, файлы Images и Strings.resx из моего проекта WPF в библиотеку классов.
Таким образом, проект, не WPF, может использовать тот же проект.
Для этого я создал новую библиотеку классов и переместил файлы в новый проект, убедившись, что действие сборки для изображений — это ресурс, как это было в проекте WPF.
Затем я заметил, что мои изображения не включены в файл *.dll и механизм «ресурсов» не работает.
Когда я делаю то же самое, НО, с таргетингом библиотеки классов .NET Framework 4.8, а не .NET 8.0, все работает так, как задумано.
Я также заметил, что когда я определяю <UseWPF>true</UseWPF> в своей библиотеке классов .NET 8.0, он также работает так, как задумано.
К сожалению, найденные обходные пути не работают для меня, так как я не хочу, чтобы .NET Framework 4.8 и UseWpf включали нежелательные зависимости в проект, отличный от wpf, например. Blazor Project, когда я делюсь библиотекой классов.
Я проверил недостающие ресурсы с помощью dotPeek, вот скриншот, на котором вы можете увидеть разницу между двумя целевыми платформами:
@Selvin - Я думаю, вы путаете Resource и EmbeddedResource, см., например. stackoverflow.com/questions/9419611 - в моем проекте cs действие сборки определено как ресурс <ItemGroup> <Resource Include = "Images\*.*" /> </ItemGroup> - и да, библиотека классов .NET 8 работает со встроенными ресурсами, но WPF не знает изображений, поскольку ищет ресурсы
@Selvin - вот скриншот, показывающий мою проблему - i.sstatic.net/IYSj9lBW.png
ClassLibrary2 работает либо путем объявления UseWPF ИЛИ изменения целевой платформы на net48, но оба решения нежелательны.
@RandRandom, вы хотите создать общую библиотеку классов для изображений как с .NET Framework 4.8, так и с .NET 8.0?
@MustafaMutasim - нет, общая библиотека между проектом .NET 8 wpf и, например. проект .NET 8 blazor - оба .NET 8, НО разные типы проектов, например. рабочий стол и консоль или рабочий стол и Интернет, или рабочий стол Windows и терминал MacOS
@MustafaMutasim - и я не могу настроить .net framework 4.8 или использовать UseWPF, когда библиотеку классов следует использовать на MacOs
@RandRandom, можешь, я опубликую свой ответ на WPF и MAUI ты можешь начать с него
@RandRandom это как-то работает
@Selvin - как я уже сказал, EmbeddedResource действительно работает в библиотеке классов, НО я не могу использовать его в приложении WPF, потому что оно его не найдет, потому что ищет ресурс. посмотрите еще раз: i.sstatic.net/IYSj9lBW.png - где вы можете видеть, что WPF загружает изображение только в том случае, если оно объявлено как Resource, а UseWPF объявлен (ClassLibrary2).
@RandRandom EmbeddedResource используется для g.resx, а не для изображения... изображение находится в файле resx (в моем последнем «примере изображения»)... добавьте «g.resx» типа Resource в проект, удалите, отключите генерацию кода и удалите g Файл .Designer.cs... добавить изображение в файл resx... изменить имя изображения в resx
@Selvin - окей, извини, похоже, это я недостаточно внимательно рассмотрел твое изображение, я попробую
ок, без прикольного g.resx имени... можно обойтись <ItemGroup> <EmbeddedResource Update = "Resource.resx"> <LogicalName>$(AssemblyName).g.resources</LogicalName> </EmbeddedResource> </ItemGroup> обычным Resource.resx
@Selvin - спасибо за идею, очень интересно - я могу проверить, что ILSpy показывает изображение, НО dotPeek не распознает его, как и WPF - так что, к сожалению, по неизвестной причине это не работает - может быть, вы есть идея, почему WPF, похоже, не нравится этот подход? i.sstatic.net/c9PmlugY.png
Требуется ли встраивание файлов изображений в сборку? В противном случае вы можете установить для их действия Build Action значение Content и загружать их из WPF по siteoforigin URI.
единственная разница - <data name = "images/logo.png" mimetype = "application/x-microsoft.net.object.binary.base64"><value> и <data name = "images/logo.png" type = "System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"><value> ... это глупо ... это работает в VS, но не в исполняемом файле ... кажется, здесь проблема?
@Клеменс - не совсем, пока WPF может с ними справиться, мне действительно все равно - единственная причина, по которой они являются ресурсами, заключается в том, что именно так вы и должны это делать.
Хорошо, просто добавьте файлы изображений в проект библиотеки, установите для их действия «Сборка» значение Content и «Копировать в выходной каталог» — Copy .... Предполагая, что они находятся в папке проекта с именем «Изображения», загрузите их <Image Source = "pack://siteoforigin:,,,/Images/ImageFile.jpg"/>.
лол... разница в один байт i.sstatic.net/CU7wbzur.png в .resource файле между UseWPF и моим способом... это действительно глупо (я изменяю этот один байт в dll, и теперь он отображается в dotPeek)
@Clemens - попробовал вашу идею, и, похоже, она работает с изображениями, определенными в XAML на корневом уровне, но не в подпапке, например. Controls\MyCustomControl.xaml если у этого MyCustomControl.xaml есть изображение, оно его не найдет. Прочитав некоторую документацию, я считаю, что это потому, что оно будет искать изображение по адресу Controls\Image\abc.png вместо того, чтобы идти в корень и искать там Controls\abc.png - не удалось найти правильный синтаксис, чтобы всегда смотреть в корень, возможно ли это?
Вы имеете в виду папку проекта с именем Controls, которая содержит MyCustomControl с изображением с URI источника siteoforigin? Это все еще работает для меня.
@Clemens - пытался воспроизвести проблему в фиктивном проекте, кажется, мой предыдущий диагноз был неправильным, и проблема находится в другом месте, если я смогу ее успешно воспроизвести, я вернусь к вам
@RandRandom Наконец-то я нашел решение, которое, кажется, работает
@Selvin - посмотрю завтра, спасибо за преданность делу
Кстати, вы можете настроить таргетинг на несколько фреймворков в одном проекте <TargetFrameworks>net8.0;net8.0-windows</TargetFrameworks> и добавить UseWPF условно <PropertyGroup Condition = " '$(TargetFramework)' == 'net8.0-windows' " > <UseWPF>true</UseWPF> </PropertyGroup>, тогда, если вы добавите ссылку PROJECT в проект blazor, он будет использовать net-8.0, а не net8.0-windows (если вам не нужен этот ресурс изображения в blazor)





Наконец-то заработало...
С изображением logo.png в images/logo.png этот файл csproj должен работать:
<Project Sdk = "Microsoft.NET.Sdk">
<Import Project = "..\targets\Microsoft.WinFX.targets" Sdk = "Microsoft.NET.Sdk.WindowsDesktop" />
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<None Remove = "Images\Logo.png" />
<Resource Include = "Images\Logo.png" />
</ItemGroup>
</Project>
Microsoft.WinFX.targets позволит скомпилировать <Resource /> элементы в $(AssemblyName).g.resources так же, как и в UseWPF/UseWindowsForms НО!!! не буду добавлять никаких ссылок
Разница в один байт, о которой я говорил в комментариях, заключается в том, что wpf/winforms использует System.IO.PinnedBufferMemoryStream, а не System.Byte[] для «сериализации» изображения.
Спасибо, решение, похоже, работает просто великолепно. Просто небольшое замечание, которое вызвало проблему с моей стороны. Порядок строки <Import Project... имеет значение. В моем приложении я устанавливаю <AssemblyName>MyFancyName</AssemblyName> строка импорта должна появиться ПОСЛЕ изменения имени сборки.
Система сборки с
UseWPFпо умолчанию добавляет png как<EmbeddedResource/>и без как<None />... Вам нужно<None Remove = "path/image.png" />а затем<EmbeddedResource Include = "path/image.png" />внутри<ItemGroup>