O. *_*per 11 wpf resources code-behind
我试图将PNG图形嵌入到DLL中并将其作为一个加载到Image控件中BitmapImage.但是,WPF不断抛出异常,说无法找到资源.
首先,一些最小的示例代码和重现问题的步骤:
使用空主窗口创建名为ImageResTest的WPF项目(可以将默认命名空间设置为ImageResTest).主窗口的代码隐藏文件应如下所示:
using System;
using System.Windows;
using System.Windows.Controls;
namespace ImageResTest
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
var obj = new MyData.SomeStuff.MyClass();
this.Content = obj.Img;
}
}
}
Run Code Online (Sandbox Code Playgroud)创建一个名为ImageResTestLib的类库(您可以将默认命名空间设置为ImageResTest,如上所述,因此此处讨论的所有内容都位于相同的根命名空间中).
MyData/SomeStuff/Resources.在该SomeStuff文件夹中,添加以下文件MyClass.cs:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace ImageResTest.MyData.SomeStuff
{
public class MyClass
{
public MyClass()
{
img = new Image();
{
var bmp = new BitmapImage();
bmp.BeginInit();
bmp.UriSource = new Uri(@"/ImageResTestLib;component/MyData/SomeStuff/Resources/Img.png", UriKind.RelativeOrAbsolute);
bmp.EndInit();
img.Source = bmp;
img.Width = bmp.PixelWidth;
}
}
private Image img;
public Image Img {
get {
return img;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)在Resources文件夹中添加名为PNG文件Img.png,并设置其生成的行动资源(如建议,例如,在这里).
到目前为止,这么好 - 启动这个应用程序应该创建一个窗口来实例化MyClass和检索Image由该MyClass实例创建的.该图像应该已经填充了一个BitmapImage数据,该数据是作为资源包含的图形加载的.
不幸的是,资源URI似乎有问题.到目前为止,MSDN上的文档没有帮助.
我尝试了以下资源URI变体:
/AssemblyName;component/Path/Filename- 在这里和这里被建议,但是DirectoryNotFoundException抛出了一个,表示C:\ImageResTestLib;component\MyData\SomeStuff\Resources\Img.png没有找到路径的一部分.pack://application:,,,/MyData/SomeStuff/Resources/Img.png在这里,这里,这里和这里建议,但抛出一个IOException说法,mydata/somestuff/resources/img.png无法找到资源.pack://application:,,,/ImageResTestLib;component/MyData/SomeStuff/Resources/Img.png在这里以及这里也提出了这个建议,但是却引发了一个FileNotFoundException说法ImageResTestLib, Culture=neutral或者其中一个依赖关系未找到的说法.Resources/Img.png(相对于代码文件)隐含在这里和这里,但抛出一个未找到的DirectoryNotFoundException说法C:\Users\myusername\Documents\Test\DOTNET\WPFTest\ImageResTest\bin\Debug\Resources\Img.png.MyData/SomeStuff/Resources/Img.png(相对于项目),也为暗示这里,作用类似于前一个.由于这些都不起作用,我尝试了以下基于以下方法的解决方法ResourceDictionary:
SomeStuff.BitmapImage使用密钥添加资源img.像这样更改MyClass.cs的内容:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace ImageResTest.MyData.SomeStuff
{
public class MyClass
{
public MyClass()
{
ResourceDictionary dict = new ResourceDictionary();
dict.Source = new Uri("/ImgResTestLib;component/MyData/SomeStuff/MyClassResources.xaml", UriKind.RelativeOrAbsolute);
img = new Image();
{
var bmp = (BitmapImage)dict["img"];
img.Source = bmp;
img.Width = bmp.PixelWidth;
}
}
private Image img;
public Image Img {
get {
return img;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)现在,可以从指示的URI加载资源字典(当删除资源字典的内容时,加载成功完成).但是,使用类似路径时仍未找到PNG图形/ImageResTestLib;component/MyData/SomeStuff/Resources/Img.png.
我做错了什么以及如何加载相应的资源(如果可能,没有额外的资源字典)?
编辑:更多信息:
FileNotFoundException我根据Ian的代码得到的堆栈跟踪如下:
System.Windows.Markup.XamlParseException: Zeilennummer "3" und Zeilenposition "2" von "Durch den Aufruf des Konstruktors für Typ "ImageResTest.Window1", der den angegebenen Bindungseinschränkungen entspricht, wurde eine Ausnahme ausgelöst.". ---> System.IO.FileNotFoundException: Die Datei oder Assembly "ImageResTestLib, Culture=neutral" oder eine Abhängigkeit davon wurde nicht gefunden. Das System kann die angegebene Datei nicht finden.
bei System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
bei System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
bei System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
bei System.Reflection.Assembly.Load(AssemblyName assemblyRef)
bei System.Windows.Navigation.BaseUriHelper.GetLoadedAssembly(String assemblyName, String assemblyVersion, String assemblyKey)
bei MS.Internal.AppModel.ResourceContainer.GetResourceManagerWrapper(Uri uri, String& partName, Boolean& isContentFile)
bei MS.Internal.AppModel.ResourceContainer.GetPartCore(Uri uri)
bei System.IO.Packaging.Package.GetPartHelper(Uri partUri)
bei System.IO.Packaging.Package.GetPart(Uri partUri)
bei System.IO.Packaging.PackWebResponse.CachedResponse.GetResponseStream()
bei System.IO.Packaging.PackWebResponse.GetResponseStream()
bei System.IO.Packaging.PackWebResponse.get_ContentType()
bei System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri, Stream stream, BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable, Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream, SafeFileHandle& safeFilehandle)
bei System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
bei System.Windows.Media.Imaging.BitmapImage.FinalizeCreation()
bei System.Windows.Media.Imaging.BitmapImage.EndInit()
bei ImageResTest.MyData.SomeStuff.MyClass..ctor(Uri baseUri) in C:\Users\username\Documents\Test\DOTNET\WPFTest\ImgResTestLib\MyData\SomeStuff\MyClass.cs:Zeile 36.
bei ImageResTest.Window1..ctor() in c:\Users\username\Documents\Test\DOTNET\WPFTest\ImageResTest\Window1.xaml.cs:Zeile 17.
--- End of inner exception stack trace ---
bei System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
bei System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
bei System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
bei System.Windows.Application.LoadBamlStreamWithSyncInfo(Stream stream, ParserContext pc)
bei System.Windows.Application.LoadComponent(Uri resourceLocator, Boolean bSkipJournaledProperties)
bei System.Windows.Application.DoStartup()
bei System.Windows.Application.<.ctor>b__1(Object unused)
bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
bei MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
bei System.Windows.Threading.DispatcherOperation.InvokeImpl()
bei System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Windows.Threading.DispatcherOperation.Invoke()
bei System.Windows.Threading.Dispatcher.ProcessQueue()
bei System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
bei MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
bei MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
bei MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
bei System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
bei MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
bei MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
bei System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
bei System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
bei System.Windows.Threading.Dispatcher.Run()
bei System.Windows.Application.RunDispatcher(Object ignore)
bei System.Windows.Application.RunInternal(Window window)
bei System.Windows.Application.Run(Window window)
bei System.Windows.Application.Run()
bei ImageResTest.App.Main() in c:\Users\username\Documents\Test\DOTNET\WPFTest\ImageResTest\obj\Debug\App.g.cs:Zeile 0.
Run Code Online (Sandbox Code Playgroud)
EDIT2:
添加
Debug.WriteLine(typeof(MyData.SomeStuff.MyClass).Assembly.GetName().FullName);
Run Code Online (Sandbox Code Playgroud)
到主窗口的构造函数导致以下输出:
ImgResTestLib, Version=1.0.5123.16826, Culture=neutral, PublicKeyToken=null
Run Code Online (Sandbox Code Playgroud)
打电话给
Debug.WriteLine(BaseUriHelper.GetBaseUri(this).ToString());
Run Code Online (Sandbox Code Playgroud)
打印以下内容:
pack://application:,,,/ImageResTest;component/window1.xaml
Run Code Online (Sandbox Code Playgroud)
EDIT3:
虽然接受的答案解决了这个问题所描述的问题,但为什么我在实际项目中看不到我的图形的实际原因却完全不同:
虽然VS 2010和SharpDevelop都没有给出任何指示,但标记为Resource的资源实际上具有逻辑名称(在我的情况下,它们保留了我从暂时将构建操作设置为EmbeddedResource并更改逻辑名称时).逻辑名称仍然出现在<LogicalName>MSBuild文件的元素中,并且从我在ILSpy中可以看到的内容,即实际用作已编译程序集中的资源名称的内容.
具有逻辑名称的这种资源的正确(工作)资源URI 似乎是
/MyAssembly;component/LogicalResourceName
Run Code Online (Sandbox Code Playgroud)
(因此像通常的EmbeddedResource资源一样,替换资源的目录路径)
虽然在构建操作设置为Resource时无法更改VS或SharpDevelop中的逻辑名称,但删除资源并重新添加文件,然后将构建操作设置为Resource,使基于文件名的URI再次起作用逻辑名称将不再出现在项目文件中.同样,<LogicalName>从MSBuild文件中手动删除元素应该可以工作.
Ian*_*ths 18
部分问题是WPF没有用于解析该URL的上下文.它是一个相对URL,通常,它将相对于使用它的XAML内容的基URI进行解析.如果我在此代码中使用完全相同的URL:
public MainWindow()
{
InitializeComponent();
var img = new Image();
Content = img;
var bmp = new BitmapImage();
bmp.BeginInit();
bmp.UriSource = new Uri(@"/ImageResTestLib;component/MyData/SomeStuff/Resources/Img.png", UriKind.RelativeOrAbsolute);
bmp.EndInit();
img.Source = bmp;
img.Width = bmp.PixelWidth;
}
Run Code Online (Sandbox Code Playgroud)
然后它工作.MainWindow显然,那是在代码隐藏中.
通过一个微小的变化,移动这一行:
Content = img;
Run Code Online (Sandbox Code Playgroud)
到最后,然后我DirectoryNotFoundException和你一样.
WPF尝试将该URI解析为实际资源,并将其指定BitmapImage为该Source属性Image.我的第一个例子是有效的,因为Image它位于可视树中,因此它获取了基本URI MainWindow.xaml,并解析了相对于该基URI的资源URI.
如果你真的需要创建它Image之前它与可视树相关联,你有各种选择.您实际上可以在图像上设置基本URI:
img.SetValue(BaseUriHelper.BaseUriProperty, baseUri);
Run Code Online (Sandbox Code Playgroud)
然而,这有点奇怪.构建绝对URI更容易,例如:
bmp.UriSource = new Uri(
baseUri,
@"/ImageResTestLib;component/MyData/SomeStuff/Resources/Img.png");
Run Code Online (Sandbox Code Playgroud)
这两个当然都假定您知道基URI是什么.您可以通过在MainWindow构造函数中询问来找到它:
public MainWindow()
{
InitializeComponent();
var baseUri = BaseUriHelper.GetBaseUri(this);
...
Run Code Online (Sandbox Code Playgroud)
在你的情况下,那将是: pack://application:,,,/ImageResTest;component/mainwindow.xaml
这反过来说明了解析的URI应该是什么: pack://application:,,,/ImageResTestLib;component/MyData/SomeStuff/Resources/Img.png
有趣的是,你说你试试并得到一个错误.好吧,我正在尝试那个确切的URI,而且我没有收到错误.为了清楚起见,这是我的MyClass构造函数的修改版本:
public MyClass(Uri baseUri)
{
img = new Image();
var bmp = new BitmapImage();
bmp.BeginInit();
bmp.UriSource = new Uri(baseUri, @"/ImageResTestLib;component/MyData/SomeStuff/Resources/Img.png");
bmp.EndInit();
img.Source = bmp;
img.Width = bmp.PixelWidth;
}
Run Code Online (Sandbox Code Playgroud)
这是我的MainWindow构造函数:
public MainWindow()
{
InitializeComponent();
var obj = new MyData.SomeStuff.MyClass(BaseUriHelper.GetBaseUri(this));
this.Content = obj.Img;
}
Run Code Online (Sandbox Code Playgroud)
这对我有用,遵循了你的指示.如果我理解正确的话,你会看到FileNotFoundException你这样做的时候.这让我想知道你的指示是否遗漏了什么.例如,如果ImageResTestLib被强烈命名,我希望看到这个错误.(如果要引用强命名库中的资源,则需要在部件之前使用完全限定的程序集显示名称;component.)
另一种选择是Application.GetResourceStream与BitmapImage.StreamSource财产一起使用.但同样,这将需要一个有效的URL,因此您可能会遇到与以前相同的问题.一旦你弄清楚你的项目中有什么不同就停止pack://application:,,,/ImageResTestLib;component/MyData/SomeStuff/Resources/Img.png了工作,那么你已经拥有的基本方法应该没问题.
| 归档时间: |
|
| 查看次数: |
27409 次 |
| 最近记录: |