Windows Presentation Foundation 4.5 Cookbook
上QQ阅读APP看书,第一时间看更新

Accessing binary resources in code

Accessing a binary resource in XAML is pretty straightforward, but this works for standard resources such as images. Other types of resources may be used in code, and this requires a different approach.

Getting ready

Make sure Visual Studio is up and running.

How to do it...

We'll create an application that shows book information read programmatically from an XML file stored as a resource:

  1. Create a new WPF Application named CH02.BinaryResourcesInCode.
  2. Add the books.xml (found in the downloadable source for this chapter) file as a resource (make sure Build Action is set to Resource). As an alternative, you can create the file yourself and type its contents as shown in the next step.
  3. The books.xml file looks something like the following:
    <Books>
       <Book Name="Windows Internals" Author="Mark Russinovich" />
       <Book Name="Essential COM" Author="Don Box" />
       <Book Name="Programming Windows with MFC" 
             Author="Jeff Prosise" />
    </Books>
  4. Open MainWindow.xaml. Add two rows to the Grid with a TextBox and a Button:
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Button Content="Read Book Data" FontSize="14" />
            <TextBox Grid.Row="1" IsReadOnly="True" x:Name="_text"
                     FontSize="16" Margin="4"/>
        </Grid>
  5. Add a Click event handler to the button.
  6. Inside the Click event handler, we want to get to the books.xml resource. Add the following code:
    var info = Application.GetResourceStream(new Uri("books.xml", 
        UriKind.Relative));
  7. This returns a StreamResourceInfo. Now we can access the Stream property and use it in any way we want. Here's an example (you'll need to add a using System.Xml.Linq statement):
    var books = XElement.Load(info.Stream);
    var bookList = from book in books.Elements("Book")
                   orderby (string)book.Attribute("Author")
                   select new {
                      Name = (string)book.Attribute("Name"),
                      Author = (string)book.Attribute("Author")
                   };
    foreach(var book in bookList)
       _text.Text += book.ToString() + Environment.NewLine;
  8. Running the application and clicking the button produces the following:
    How to do it...

How it works...

The Application.GetResourceStream static method provides a programmatic way of accessing a resource using its relative URI (or absolute with the pack scheme). It returns a StreamResourceInfo object, which contains two properties: ContentType returns the MIME type (such as image/jpeg or text/xml) and, more importantly, the Stream property which provides access to the actual binary data.

If the resource has been marked with a Build Action of Content, then the similar looking Application.GetContentStream method should be used instead.

In the previous example, we've used the XElement class (from the relatively new LINQ to XML API) to turn the binary data into a XElement object. Then we use that object to query and display some data.

There's more...

There's actually another way to get to a resource while using core .NET types such as ResourceManager and ResourceSet (that have been around since .NET 1.0) instead of calling Application.GetResourceStream. Here's one way to get the Stream of a resource:

Stream GetResourceStream(string name) {
   string asmName = Assembly.GetExecutingAssembly().GetName().Name;
   var rm = new ResourceManager(asmName + ".g",
       Assembly.GetExecutingAssembly());
         using(var set = rm.GetResourceSet(
            CultureInfo.CurrentCulture, true, true)) {
      return (Stream)set.GetObject(name, true);
   }
}

This just shows that WPF has no special support for binary resources and in fact it leverages core .NET functionality in this regard.

Note that there's no counterpart for a resource on which Build Action was set to Content.