After a lot of trial and error I came up with a workaround which I thought I'd share.
I created new class, ImageData
to encapsulate the relative Uri which I needed to load into the Image
control.
public class ImageData
{
/// <summary>
/// Relative path to image
/// </summary>
public string ImageSourceUri { get; set; }
public ImageSource ImageSource
{
get { return new BitmapImage(App.GetPathUri(ImageSourceUri)); }
}
}
Then I created a function in the App
class (for convenience) to convert the relative path into an absolute Uri.
/// <summary>
/// Converts a relative path from the current directory to an absolute path
/// </summary>
/// <param name="relativePath">Relative path from the current directory</param>
public static string GetPath(string relativePath)
{
return System.IO.Path.Combine(Environment.CurrentDirectory, relativePath);
}
/// <summary>
/// Converts a relative path from the current directory to an absolute Uri
/// </summary>
/// <param name="relativePath">Relative path from the current directory</param>
public static Uri GetPathUri(string relativePath)
{
return new Uri(GetPath(relativePath), UriKind.Absolute);
}
Finally, I created a DataTemplate
in XAML, again in the App.xaml file for convenience:
<Application.Resources>
<DataTemplate DataType="{x:Type local:ImageData}">
<Image Source="{Binding Path=ImageSource}"></Image>
</DataTemplate>
</Application.Resources>
Now when the XamlWriter.Save
method is called, the XAML that is outputted looks like this:
<d:ImageData ImageSourceUri="test_local.png" />
So the paths get stored as relative paths, of type string
, and then when the XAML is loaded in again using XamlReader.Load
, the DataTemplate binds to the ImageSource
property, which converts the relative path to an absolute one as late as possible.