Even a chimp can write code

Saturday, November 05, 2005

Resources in Windows Presentation Foundation applications

I've been wanting to blog about the application files and resources story in WPF, but couldn't get to it thus far. Recently I responded to a newsgroup question on how WPF (Avalon) handles resources, and figured that would make a good blog post until the WinFX SDK content for this goes online.

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. If you're curious about resources in WPF or even as a historical perspective of what we enabled in the resource resolution and loading space in WPF before we created the subset in Silverlight, then read on.

Background
Resources are non-executable data deployed with an application. They may take the form of images displayed in the UI or message strings for error messages. The .NET Framework provides built-in support for creating, localizing, packaging and deploying resources. You can create resources in a .resx or a .resources file. The .resx resource file format consists of XML entries to specify objects and strings. If your application has an image, the binary form of that image is serialized into the .resx file. But although a .resx file can be edited via a text editor, it cannot directly be added to an application executable or satellite assembly. You must first convert it to a .resources file using a tool like ResGen.exe and add the .resources file into the assembly. The GenerateResource task in MSBuild handles the conversion of .resx to .resources at build time. In your WinForms project, you'd specify the EmbeddedResource build action for .resx files.
For e.g.

<EmbeddedResource Include="myResources.resx"/>

How we do it in Avalon
In Windows Presentation Foundation, the resource definition and loading model is different from the WinForms model. First, we do not require you to create .resx files. You merely indicate your resources in the project file and the WPF build system will take care of the rest. Second, unlike with .NET resources which have resource ids, in WPF you need to reference a resource in XAML via a Uri. WPF also supports the multi-lingual user interface (MUI) assembly model where language-neutral resources go into the main assembly and language-specific resources go into corresponding language-specific satellite assemblies. For these purposes, a new set of resource build actions were created. These are the Resource and Content build actions. Both these build actions target application files that are known at compile time.

Resource
If a file is denoted 'Resource' in the project file, upon build, that file is embedded into the application assembly. Whether main or satellite assembly, depends on whether you've set the 'Localizable' meta-data. The default is main assembly.
For e.g.

<Resource Include="AmateurDictators/RoderickSpode.jpg"/>

The ResourcesGenerator task in the WPF MSBuild system (in Microsoft.WinFX.targets) creates a single .resources file for all Resources specified in the project. In a localized application, the application will load the resource from the appropriate satellite assembly based on the locale of the computer where it is running. In a future post I will talk about the resource fallback logic in WPF.

Content
If a file is denoted as 'Content' with the appropriate 'CopyToOutputDirectory' meta-data set to 'Always' or 'PreserveNewest', the file is treated as loose application content and is copied to the build output directory, residing alongside the application assembly.
For e.g.

<Content Include="Drones/GussyFink-Nottle.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>

Regardless of whether you denote a file as 'Resource' or 'Content', you can access it in markup and code via a simple relative Uri. For e.g.

<Image Source="AmateurDictators/RoderickSpode.jpg" />
<Image Source="Drones/GussyFink-Nottle.png" />

During build, a mapping of all Content files in an application is created. At runtime, when confronted with a relative Uri, the loading mechanism knows if the object is a loose Content file or a Resource embedded in the application assembly.

Files at site of origin
If you do not want to be bound by the restrictions of having your application resources declared at compile time, there is another option for you. No, this doesn't involve using fully qualified Uris to reference resources over the internet. Although, that is indeed supported. WPF provides you with an abstraction for the application's conceptual site of origin i.e. the location from where the application was deployed. For instance, if your application was launched from http://nerddawg.blogspot.com, then your application's site of origin is http://nerddawg.blogspot.com. To access an image at images/AuntDahlia.gif at that location, you would specify in markup:

<Image Source="pack://siteoforigin:,,,/images/AuntDahlia.jpg" />

You can use the same Uri in code. For more on the Pack Uri syntax, see the Appendix in the XPS spec. I will provide more details in a future post.

Choosing one over the other
You would choose to mark a file as Resource if:

  • your file is localizable i.e. images with text in them, fonts or text files

  • you don't expect to replace the file once the application has been built

  • you don't want to deal with the task of managing and deploying the file separately from the application i.e. you want to be able to move the application around without having to worry about moving several associated files


And, you would choose to mark a file as Content if:

  • your file is not localizable

  • you want the flexibility of replacing the file after the application assemblies have been built

  • you want to be able to have the file download on demand (i.e. not with the application assembly)

  • WPF cannot load a file of this type when it is embedded into the application assembly e.g. HTML content rendered in a Frame, media files


Finally, you would choose the site of origin notation if:

  • your file is not localizable

  • you want the flexibility of replacing the file after the application assemblies have been built

  • you want to be able to have the file downloaded only when requested

  • you don't know the contents of the file (or you don't really have the file) when you build the application

  • your file is very large and you don't want that to affect the application download time e.g. large media files

  • WPF cannot load a file of this type when it is embedded into the application assembly e.g. HTML content rendered in a Frame, media files


There is currently no support for strongly typed 'Resource' and 'Content' files in the WPF project templates. 'EmbeddedResources' are supported, however, they cannot be referenced via Uris.

Tags:

Email this | Bookmark this

7 Comments:

  • You touched very hot topic,discussed recently on
    http://forums.microsoft.com/msdn/ShowForum.aspx?ForumID=119.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'm big fun of web deployment model-highly flexible and dynamic environment by nature;-)But I want prototype my app abilities as win app with pack:// uri syntax,so how c:\test\test.jpg will looks in pack://?

    Thanks a lot.

    By Anonymous Anonymous, at December 2, 2005 at 5:04 AM  

  • I posted a clarification in this new entry: More on resource loading in WPF. Hope that answers your questions.

    -Ashish

    By Blogger Ashish Shetty, at December 3, 2005 at 9:41 AM  

  • This is a newbie. Charles Petzold in one of his books mentions that Windows resources include 'menus' and 'dialog boxes'. Are these still considered 'resources' in the .NET model ? How can a dialog box be a resource when it is an executable ?

    Thanks,

    Chakravarthy

    By Anonymous Anonymous, at January 3, 2006 at 12:33 PM  

  • I don't know the context in which Charles Petzold made that statement, so I cannot comment on that directly. Besides, the term 'resource' is so generic that is is used in a wide variety of places with different connotations.

    In .NET and moreover with Windows Presentation Foundation, we use the term 'Resource' to refer to non-executable data that accompanies an application. This can be an image file to decorate your menu backgrounds, an XSL file for transformation or a text file holding default configurations. In the .NET world, menus and dialogs have backing code. In WPF, you can declare a menu or dialog in XAML markup (which is converted to code during build) or directly in code files. I hope that makes it somewhat clearer.

    By Blogger Ashish Shetty, at January 3, 2006 at 1:19 PM  

  • Talking about chimps.... It is quite clear that the Charles Petzold book being referred to is talking about Win32 in some way.

    Ashish, that you suggest that 'Resource' is a widely generic name is true. But only because MS has used it in two areas to mean two completely different things.

    In the 'original' form it meant a binary file that was attached to an EXE which included images,bitmaps,menus,dialogs and the like.
    In .NET they reused the term to mean something similar, but they are NOT .res files by any long shot. They do not include Form layouts.

    WPF abstracts the idea of Form layout even further to add XAML files.
    Trust MS to create unecessarily confusing names.

    By Anonymous Anonymous, at March 26, 2007 at 11:50 PM  

  • Very useful article -- even if the P.G. Wodehouse references are distracting :)

    By Anonymous Anonymous, at March 19, 2008 at 8:58 AM  

  • This article is rubbish. Get a different job

    By Anonymous Anonymous, at November 6, 2009 at 10:40 AM  

Post a Comment | Home | Inference: my personal blog