5

I have an image on my wpf page which opens an image file form hard disk. The XAML for defining the image is:

  <Image  Canvas.Left="65" Canvas.Top="5" Width="510" Height="255" Source="{Binding Path=ImageFileName}"  />

I am using Caliburn Micro and ImageFileName is updated with the name of file that image control should show.

When the image is opend by image control, I need to change the file. But the file is locked by image control and I can not delete or copy any mage over it. How can I force Image to close the file after it opened it or when I need to copy another file over it?

I checked and there is no CashOptio for image so I can not use it.

user1731110
  • 75
  • 1
  • 5
  • 1
    Post you Get for ImageFileName. Are you closing the file there? – paparazzo Oct 12 '12 at 21:00
  • @Blam: The ImageFileName is something such as this: c:\tmp\testimage.jpg and I am not opening or closing it by myself. It is the Image control which opens it and not closing it. – user1731110 Oct 12 '12 at 21:03
  • See [this question and answer](http://stackoverflow.com/q/12799931/1136211). In your case it may make sense to write a binding converter that converts the file name to an ImageSource. – Clemens Oct 12 '12 at 21:11
  • Exactly. Need a different pattern so the control is not accessing a file. Do it in the converter or the get. – paparazzo Oct 12 '12 at 22:07

1 Answers1

12

You could use a binding converter like below that loads an image directly to memory cache by setting BitmapCacheOption.OnLoad. The file is loaded immediately and not locked afterwards.

<Image Source="{Binding ...,
                Converter={StaticResource local:StringToImageConverter}}"/>

The converter:

public class StringToImageConverter : IValueConverter
{
    public object Convert(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        object result = null;
        var path = value as string;

        if (!string.IsNullOrEmpty(path))
        {
            var image = new BitmapImage();
            image.BeginInit();
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.UriSource = new Uri(path);
            image.EndInit();
            result = image;
        }

        return result;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Even better, load the BitmapImage directly from a FileStream:

public object Convert(
    object value, Type targetType, object parameter, CultureInfo culture)
{
    object result = null;
    var path = value as string;

    if (!string.IsNullOrEmpty(path) && File.Exists(path))
    {
        using (var stream = File.OpenRead(path))
        {
            var image = new BitmapImage();
            image.BeginInit();
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.StreamSource = stream;
            image.EndInit();
            result = image;
        }
    }

    return result;
}
Clemens
  • 123,504
  • 12
  • 155
  • 268