1

During serialization with a XamlWriter, among other things I am trying to serialize Image controls. These Source property of these controls is set to a relative URI.

However, after serializing with the XamlWriter, the Image controls contain paths like this:

Original Path

../test.png

XamlWriter Path

pack://application:,,,/test.png

Is there any way to prevent the XamlWriter from changing relative paths to pack paths?

ose
  • 4,065
  • 2
  • 24
  • 40
  • Check out this question: http://stackoverflow.com/questions/6495253/how-to-prevent-xamlwriter-save-from-serializing-the-baseuri-property – corylulu Feb 04 '12 at 09:40

1 Answers1

0

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.

ose
  • 4,065
  • 2
  • 24
  • 40
  • As a side note, whether to place the GetPath logic in the App class or not is a design consideration - depending on the context it may reduce coupling to place it as a private method in the ImageData class.. – ose Feb 04 '12 at 11:40