I want to be able to store multiple FlowDocuments within a single package, including images, etc. within each document. However, none of the methods I've seen for saving (and loading) Xaml FlowDocuments seem capable of this.
It's pretty annoying that there's no one-stop way of serializing a FlowDocument and its images, etc. to a PackagePart. If anyone's figured out a good way of doing this, how'd you pull it off?
UPDATE 2011-07-03 00:22: Using XamlWriter and some extra code from this question I've been able to build a happy little OPC-compliant package which can hold multiple FlowDocuments including their images, as PackageParts. However, going the other way (from PackagePart to FlowDocument) is failing, because no matter how I try to load the document, I get XamlParseExceptions telling me that
'Initialization of 'System.Windows.Media.Imaging.BitmapImage' threw an exception.'
So, the question now becomes, how do I manhandle XamlReader.Load and/or my part's stream in order to get the related images loaded properly?
Figured it out. The solution is to manually process the Xaml document before handing it over to XamlReader. Images (and other elements stored as their own PackageParts) need to have the BitmapImage.UriSource property set to include the package Uri (for example, "./Image1.png" in /Content/Document.xaml to "pack://file:,,,C:,Projects,Package.pak/Content/Image1.png").
Two caveats, however:
There's an issue with PackUriHelper.Create(Uri,Uri)
however. Instead of using
PackUriHelper.Create(packUri, part.Uri))
you have to use
new Uri(packUri.ToString() + value)
where value
is part.Uri with the initial / removed. If you don't do this, instead of getting a proper Uri like above, you get one with an additional comma after the package file name, which confuses and annoys XamlReader.
You need to use FileShare.Read when opening the package, as XamlReader will try and open it itself. By default, Package.Open locks out anyone else trying to open the package, and XamlReader.Load will throw a WebException if it can't get into the package itself.