« How to suck more as an airline or business | Main | Great WPF hands on lab posted for an Outlook 2007 visual clone »

Pack syntax in WPF

If you do much with WPF, at some point you'll be forced to use the pack syntax.

A bit of history:

The pack syntax was created by an evil-alien empire bent on mental destruction of application developers on the planet Earth.

The pack syntax is rooted in conventions established by the Open Packaging Conventions. Sigh. Designed and intended for use by committees.

The syntax is well documented, if you can find it. I came across one of the best resources for learning about the most common options used in WPF here:

Pack URIs in Windows Presentation Foundation

The trouble is actually deciphering it all. The graphic on that referenced page makes great sense -- once you can wrap your head around it. :)

I'll reiterate some of the common scenarios here. I've seen the same ones pop up in the WPF forums time and time again.

The pack syntax for files within your WPF application is easy, usually no more than a forward slash followed by the file name:

"/MyPage.xaml"

If the file is contained within a subfolder within your main application, just include the folder name:

"/Pages/MyPage.xaml"

image

If the content is relative to the current markup file or code, leave off the forward slash at the beginning, which indicates it's in the root of the application. I'll typically leave it in to be more clear where I'm getting the content from.

But, what if you are referencing Pages in another assembly you've referenced in your project?

The syntax is similar:

"/ExternalPages;component/FancyPages1.xaml"

if the file is in the main "root" folder of the referenced assembly. In this case, the referenced assembly was named "ExternalPages". The ;component syntax is required as part of the pack syntax for referenced content in external assemblies.

If the content is in a different folder:

"/ExternalPages;component/AwesomePages/IncrediblePage1.xaml"

image

If you're referring to content in the secondary assembly and loading it via the pack syntax, you'll need to reference the assembly by name, even though the content is located in that assembly. If, for example, in the ExternalPages project I had a class that loaded FancyPages1.xaml, I'd need to use syntax like this in VB.NET:

Dim u as Uri = New Uri("/" + Me.GetType().Assembly.GetName().Name + ";component/FancyPages1.xaml", UriKind.Relative))

or in C#:

Uri u  = new Uri("/" + this.GetType().Assembly.GetName().Name + ";component/FancyPages1.xaml", UriKind.Relative));

Rather than hard code the name of the assembly, I've taken the approach of grabbing it dynamically in the example above.

What's this about "pack" though? It's really how you specify the type of Uri (and where). You need to use the pack syntax when you're specifying an 'absolute' Uri. It hardly changes the common cases though (which is great!).

The pack syntax for example for the hard coded referenced assembly example above would look like this:

"pack://application:,,,/ExternalPages;component/AwesomePages/IncrediblePage1.xaml"

There's one other type of pack that's typically used when you have "loose" Xaml content, and that's the siteoforigin. The huh? Just think of it as a real "absolute" path to the location where your content lives, relative your your application's executable.

If I used this syntax:

pack://siteoforigin:,,,/MyLoosePage.xaml

That would mean that the content would come from a xaml page called MyLoosePage.xaml that was in the same folder as the application as content -- not embedded as a resource. (What's cool about this is that it also works if your application was downloaded via the web as an XBAP -- the site of origin becomes the host application virtual directory (like http://www.wiredprairie.us/myxbap for example could be the host of an Xbap -- that would become the site of origin).

Comments

Hey,

Nice post! The more the merrier on Pack URIs :)

FYI - I wrote the MSDN doc that you refer to and agree with you that it was a little tricky to get into. I've updated the doc recently to be slightly less abstract, and to have more common examples.

The doc should be out with the next online/offline updates.

Great post, but where was it three weeks ago when I was trying to work this out for myself with nothing but a couple of MSDN forum posts to go on?
The pain.. the agony..
:(

Great article! The pack syntax is just great! (Not!)

Anyway, Can I do this:
Run an Xbap with a "bootstrap" page, only the bootstrap page's dll is in the XBap manifest.
Then navigate to pages (not loose ones, real ones!) within dlls found in the site of orign but not included in the XBap manifest using this synatx? will this cause on demand download of the dll and all its dependencies or am I dreaming?

Thanks!

I'm not sure honestly -- I'd think it should work, but I've never tried.

Help support my web site by searching and buying through Amazon.com (in assocation with Amazon.com).