WPF provides ResourceDictionaries as a convenient way of adding resources like Styles to your application to be accessed when needed. However, if a non-executable resource gets very large and/or is used infrequently, resource files are a better choice than ResourceDictionairies.
With WPF applications you can incorporate any non-executable resources (including data files, images, audio, and video) into your application using a variety of schemes. You can even put XAML in a resource file so that you can download parts of your UI at runtime. However, if you’d like to avoid downloading/distributing the file until the user actually needs it, a site of origin resource file is your best choice. Site of origin files aren’t compiled into your application’s EXE or distributed with it (they’re not even copied to the location specified when you publish your application). Instead, they’re picked up at run time when your code accesses them.
Site of origin files are also a good choice in two other scenarios. First, if you have some content that is going to change frequently you can store the file on your website where you can update them as needed and let your applications pick them when they want them. Secondly, if your application is going to load different files depending on settings in the local configuration file, the identity of the local user, or any other basis for customization, you can put multiple versions of the file on your site and download them as needed.
Using site of origin files also avoids requiring your application to be granted full trust. In WPF you can often set properties (usually the Source property) on an element to a URI that points to a resource. For instance, you might use an Image element like this:
<ImageSource=“http://www.phvis.com/DataFile.bmp“ />
However, this option requires that your application be granted full trust. Site of origin files require only partial trust.
Implementing Site of Origin Files
The first step in using a site of origin file is to add it, or smaller stand-in for it, to your project in Visual Studio. After adding the file (or its stand-in) to your application, select the file and set its Build Action to None (this prevents the file from being compiled into your application).
At run time, you can download your file with code when the file is actually needed. The first step is to create an Uri object passing the location of the file with the pack and siteoforigin prefix:
Dim sooUri As New Uri(
"pack://siteoforigin:,,,/MyGrid.xml", UriKind.Absolute)
Once you have created the Uri, you may be able to just set the Source property of the control you want to use your file to the URI. This sets the Source property on a Frame, for instance (and assumes that the xml file downloaded in the previous example contained valid XAML):
Me.Frame1.Source = sooUri
However, this approach forces the framework to do any type casting or conversions for you. If you’re willing to write a little more code, you can take control of the process and ensure that the conversion is done the way you want. The first step is to create a StremResourceInfo object by calling the Application object’s GetRemoteStream method, passing your Uri:
Dim info As StreamResourceInfo = Application.GetRemoteStream(soouri)
Your next step is create a read object object to process the file. You call the reader’s LoadAsync method, passing the stream property of your StreamResourceInfo object. You’ll need to cast the output of this method to the right type. Assuming that that I’m downloading a XAML file containing a Grid, I’d need to create a XamlReader and cast the output as Page, like this:
Dim xrdr AsNewSystem.Windows.Markup.XamlReader()
Dim grd As Grid = CType(reader.LoadAsync(info.Stream), Page)
Me.Frame1.Content = grd
After publishing your application, it’s just a matter of dropping the file into the folder with the setup.exe file and your application will download it when your code executes.