Binary Resources

Although ResourceDictionary and the resource scope system are fine for data that can easily be contained in an object, not all resources fit comfortably into this model. Often we need to deal with binary streams. For example, images, audio, and video have efficient binary representations, but they are not particularly at home in markup, and in the world of objects they are usually represented by wrappers for the underlying data. Markup itself also presents a challenge: XAML pages must somehow get built into our applications. So a means of dealing with binary streams is needed.

WPF does not introduce any new technology for dealing with binary data. The .NET Framework has always provided mechanisms for dealing with embedded binary streams, and WPF simply uses these.

The lowest level of stream support lets you embed resource streams into any assembly. This is a simple matter of supplying the files you would like to embed to the compiler. In Visual Studio, you do this by setting a file's Build Action property to Embedded Resource. This copies the contents of the file into the assembly as an embedded stream. The stream can be retrieved at runtime using the Assembly class's GetManifestResourceStream method, as Example 12-26 shows.

Example 12-26. Retrieving assembly manifest resources

Assembly asm = Assembly.GetExecutingAssembly(); Stream s = asm.GetManifestResourceStream("StreamName");

Streams embedded in this way are called assembly manifest resources. Although WPF ultimately depends on this embedded resource mechanism, it uses it indirectly through the ResourceManager class in the System.Resources namespace. The resource manager builds on the embedded resource system, adding two features: localization, and the ability to store multiple named streams in a single low-level stream. The ResourceManager API allows you to ask for resources by name, and it will attempt to locate the most appropriate resource based on the UI culture. The "Global Applications" section, later in this chapter, describes this in more detail.

By convention, a WPF application or component puts all of its resources into a single assembly manifest resource stream called Appname.g.resources, where Appname is the name of the component or executable without the file extension. We can learn how WPF uses this resource stream by examining it using a ResourceManager. (In a real application, you use a WPF-supplied wrapper for the ResourceManager that we'll look at shortly. We're just using ResourceManager to look under the hood.) Example 12-27 shows how to retrieve a list of resource names.

Example 12-27. Listing binary resources static List<string> GetResourceNames(Assembly asm,

System.Globalization.Culturelnfo culture) {

string resourceName = asm.GetName().Name + ".g"; ResourceManager rm = new ResourceManager(resourceName, asm); ResourceSet resourceSet = rm.GetResourceSet(culture, true, true); List<string> resources = new List<string>(); foreach (DictionaryEntry resource in resourceSet) { resources.Add((string) resource.Key);

rm.ReleaseAllResources(); return resources;

Let's use this to look at the resources found inside a typical application. Figure 12-6 shows the Visual Studio Solution Explorer view for a simple WPF project. It contains the usual App.xaml file defining the application, and a single Window1.xaml file defining the user interface. This application also has an Images directory, which contains two bitmap files. As you can see from the Properties panel in the bottom half of Figure 12-6, the Build Action of Sunset.jpg has been set to Resource.*

* This has a different effect than the Embedded Resource action we saw earlier. Embedded Resource embeds the file in its own distinct assembly manifest resource. Resource embeds the file inside the Appname.g.resources assembly manifest resource that is shared by all the files with a build action of Resource.

When you add a bitmap file to a project using Add ^ New Item or Add ^ Existing Item from the context menu in the Solution Explorer, its Build Action will be set to Resource automatically, because this is the simplest way to work with binary resources in WPF. Wheel.jpg has the same setting.

Figure 12-6. An application with resources

If we were to call the GetResourceNames function in Example 12-27, and print out each string it returns, we would see the following output:

windowl.baml images/wheel.jpg images/sunset.jpg

As you can see, both of the bitmaps are present. You can use these embedded bitmaps from any element with a property of type ImageSource, as Example 12-28 shows.

Example 12-28. Using a bitmap resource <Image Source="images/wheel.jpg" />

Using a relative URL such as this one indicates that the resource is local—relative URLs can be used either when the bitmap file is in the same directory, or when it is compiled in as a resource. Because the bitmap data is embedded inside the resource stream in the application binary, there is no need to ship a separate file containing bitmap data.

The resource list also shows a windowl.baml resource. This corresponds to the Windowl.xaml file.

BAML is a binary representation of a XAML file—XAML is compiled into BAML during the compilation process. BAML is significantly more compact than XAML, so your executables are much smaller than they would be if XAML were built in.

In a WPF project, any file with a Build Action of Page is assumed to be XAML. It will be compiled into a BAML resource.

Although it's easy to load a resource with the Image element's Source property, or any property of type ImageSource, what if we want to use a resource from code? We shouldn't use the ResourceManager directly in a real application, because we would be depending on an implementation detail of WPF's resource handling. Instead, we should use the wrapper functionality provided by the Application class, because it's significantly simpler, as well as being the official documented mechanism.

Was this article helpful?

0 0
Project Management Made Easy

Project Management Made Easy

What you need to know about… Project Management Made Easy! Project management consists of more than just a large building project and can encompass small projects as well. No matter what the size of your project, you need to have some sort of project management. How you manage your project has everything to do with its outcome.

Get My Free Ebook

Post a comment