How to prevent XamlWriter.Save from serializing th

2019-05-08 03:13发布

问题:

I'm making a theme editor for a WPF application. I generate XAML files dynamically, then I compile them into a DLL that is used by the application. The code used to generate the XAML files goes along those lines:

var dictionary = new ResourceDictionary();
...

dictionary.Add(key, new BitmapImage { UriSource = new Uri(relativePath, UriKind.Relative) });
...

XamlWriter.Save(dictionary, "myDictionary.xaml");

My problem is that XamlWriter.Save also serializes the BaseUri property:

<BitmapImage BaseUri="{x:Null}" UriSource="Images\myImage.png" x:Key="myImage" />

The result is that when the application tries to fetch this image, it doesn't find it because BaseUri is not set. Normally the XAML parser sets this property (through the IUriContext interface), but when it is already set explicitly in XAML, the parser doesn't set it, so it remains null.

Is there a way to prevent the XamlWriter from serializing the BaseUri property?

If I was serializing a custom class, I could add a ShouldSerializeBaseUri() method, or implement IUriContext explicitly (I tried both options and they give the desired result), but how to do it for BitmapImage?

As a last resort, I could load the XAML file and remove the attribute with Linq to XML, but I was hoping for a cleaner solution.

回答1:

What if instead of preventing XamlWriter from writing BaseUri property we give it something that does not impact image loading? For example the following code:

<Image>
  <Image.Source>
    <BitmapImage UriSource="Resources/photo.JPG"/>
  </Image.Source>
</Image>

seems to be equivalent to

<Image>
  <Image.Source>
    <BitmapImage BaseUri="pack://application:,," UriSource="Resources/photo.JPG"/>
  </Image.Source>
</Image>

Try

  dictionary.Add("Image", new BitmapImage{
    BaseUri=new Uri("pack://application:,,"),
    UriSource = new Uri(@"Images\myImage.png", UriKind.Relative)
  });

If you try to set image source to the BitmapImage created this way from the code - it won't work. But XamlWriter.Save() produces XAML that does work when it's XAML :). Well, worth trying I hope.



回答2:

I eventually solved the problem by generating the XAML manually with Linq to XML.