More on resource loading in WPF
Andrey Skvortsov commented on that post: Could you elaborate more last variant with pack:// uri syntax for local windows app?You were speaking about win apps and suddenly jump to web based deployment model though it's completly different things IMHO.
I had touched ever so briefly on the Pack URI syntax but didn't give details because I figured that was a whole different topic on it's own, and was much better addressed by the XPS (a.k.a Metro) specification. However, I will try to clarify the issues he's raised.
The Metro package is a logical entity comprised of a number of parts. The Pack URI scheme defines a way to use URIs to refer to part resources inside a Metro package. It uses RFC 2396's (Uniform Resource Identifiers: Generic Syntax) extensibility mechanism for defining new kinds of URIs based on new schemes. You're probably aware that the scheme is the prefix in a URI, e.g. http, ftp. So Metro defines
packas a new scheme. The URI format is so:
The authority component in a Pack URI is itself an embedded URI pointing to a package. This must be a legal URI per RFC 2396. Of course, since it is embedded in the Pack URI, you must escape reserved characters. In our case, slashes ("/") are replaced by commas (","). Other characters like "%", "?" etc. must be escaped. See the spec for complete details. Windows Presentation Foundation provides an application with two built-in authorities:
applicationauthority abstracts the deployed application itself. Any resources embedded in that application assembly, one of it's satellite resource assemblies or even loose files accompanying that application may be referenced using this authority. Of course, your project must define these files as
Content, respectively. I should add though, that you need not use the Pack URI syntax for application files such as these. You can just use regular relative URIs.
siteoforiginauthority abstracts the conceptual site of origin of the deployed application. So if you had a file test.jpg at the location where the application binaries and manifests reside, say C:\myfiles\, then you need not hardcode the URL
file:///C:/myfiles/test.jpg. You can instead use the abstraction
pack://siteoforigin:,,/test.jpg. Notice that I said need not: in a full-trust application (Window-based installed application), you can do pretty much what you want. But in a web-browser application, you cannot access files on disk so adding a reference such
file:///C:/myfiles/test.jpgpretty much binds you to a full trust app, and moreover you have to worry about how to get that image into that location for everyone that uses your app.
So, to go back to Andrey's question, if he were prototyping a WPF app, it would be prudent to use these abstractions and make the app portable, no matter if the prototype started out an installed or browser-hosted app flavor. Remember that with WPF, you use the same programming model for an installed app and a browser-hosted app. You can switch between these two flavors merely by changing the
Installproperties in your project, and pretty much nothing else. Besides, ClickOnce does the heavy lifting of downloading all loose content files for your application during deployment, so you don't have to.
Is there an easier way to construct Pack URIs?
Yes, look at the
System.IO.Packaging.PackUriHelperclass and try experimenting with the
Createmethod by passing it different types of URIs as parameters.
You don't really need Pack URIs
That's right. The novice WPF programmer can survive without knowing how Pack URIs work. I've talked about how you can use simple relative URI references instead of the pack://application notations. Further, if you're looking for a package part or better still, the stream for an embedded resource you can use
Application.GetResourcePart(Uri relativeUri). To get a stream for an XML file embedded in your application:
Stream stream = Application.GetResourcePart(
To get the stream for a loose content file you can use
Application.GetContentPart(Uri relativeUri). For e.g. here's how to get a stream for a declared loose image file with your application:
Stream stream = Application.GetContentPart(
To get the stream for a file at the location from where the application was launched, you can use
Application.GetRemotePart(Uri relativeUri). For e.g. here's how to get a stream for an undeclared text file at the site of origin:
Stream stream = Application.GetRemotePart(
Update [Apr 2009]: If you came here looking for resources and URIs in Silverlight, then you will find this post helpful. Note that Silverlight does not support pack URIs.