Skip Navigation LinksHome > View Post

WPF Image element locks my local file

When using the Image element and specifying a local resource Uri in the Source attribute that resource will be locked by your application's process.

<Image Source="C:\Image\Josh.png" />

The file can't be deleted or modified whilst it's locked and this can be a problem if the image was generated and the application wants to clean it up when the user has finished looking at it. There is a simple work around for this, specifying the BitmapImage directly and specifying the CacheOption as OnLoad:

<Image>
    <Image.Source>
        <BitmapImage UriSource="C:\Image\Josh.png" CacheOption="OnLoad" />
    </Image.Source>
</Image>

But

However, there is one big problem with this. The UriSource doesn't work with a binding, e.g.:

<Image>
    <Image.Source>
        <BitmapImage UriSource="{Binding MyImageUrl}" CacheOption="OnLoad" />
    </Image.Source>
</Image>

The good news is, there's another workaround for this by implementing an IValueConverter that returns a BitmapImage with the CacheOption set to OnLoad.

public class UriToCachedImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return null;

        if (!string.IsNullOrEmpty(value.ToString()))
        {
            BitmapImage bi = new BitmapImage();
            bi.BeginInit();
            bi.UriSource = new Uri(value.ToString());
            bi.CacheOption = BitmapCacheOption.OnLoad;
            bi.EndInit();
            return bi;
        }

        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException("Two way conversion is not supported.");
    }
}

Now we can go back to using the Image tag alone, and use our new converter to return a cached BitmapImage:

<Image Source="{Binding MyImageUrl, Converter={StaticResource uriToImageConv}}"/>

... where uriToImageConv is the key of a static resource of type UriToCachedImageConverter.

Thanks to WiredPrairie for the inspiration for this workaround.

Tags: WPF

 
Josh Post By Josh Twist
12:58 PM
07 Aug 2007

» Next Post: Part III. Grabbing the ScreenShot
« Previous Post: Part II. Storing the Feedback Data

Comments are closed for this post.

Posted by GioGio @ 19 Nov 2008 2:41 AM
hey there,
that's exactly, what I needed. Thx for that.
Now, I have a question:
I added the Class UriToCachedImageConverter to my project, but how can I add a "static resource" of this class?

Posted by Josh @ 19 Nov 2008 12:05 PM
Check out this post, Xaml. Using Resources:

http://www.thejoyofcode.com/Xaml._Using_Resources.aspx

Posted by Ryan O'Neill @ 04 Feb 2009 2:41 AM
Brilliant, I kind of thought it was doing something like that but I just could not track it down. Now I can delete my images after I remove them from a ListView.

Thanks for post, it was very helpful.
Ryan

Posted by Patrik Fatoric @ 10 Feb 2009 4:06 PM
Hi,

I have a similar problem, but my image is part of control template in a Button which is situated in a DataTemplate of WPF DataGrid.
The DataTemplate is loaded dynamically as resource dictionary.

My problem is that I cannot use local resurces statically linked to my DataTemplate so I cannot
use the DataConverter.

What could I do ?

I find out, when I intentional chage the ImageSource to another existing image on disk the system release the first one. After that the first image is free to delete or chage.

Is there a better solution ?


My code ...

<Button x:Name="Img1" Width="35" Height="35">
<Button.Template>
<ControlTemplate>
<Image x:Name="img" Source="{Binding Path=Slika}" width="32" Height="32"/></ControlTemplate> </Button.Template>

Posted by Robert @ 06 Sep 2010 3:29 PM
I was having this problem with an app I am building. Someone suggested I use bitmatcacheoption.onload. It took a lot of Googling but I finally found this post and your suggestion worked like a champ. Thank you for posting it.

Posted by Igor @ 06 Dec 2010 8:52 AM
You rock!
btw: It so bad, that we can put converter's code in xaml. I hate writing these two line classes.

Posted by Josh @ 06 Dec 2010 6:40 PM
Thanks Igor,

Have you seen this: http://www.thejoyofcode.com/The_Binding_you_wanted_from_day_one_in_WPF.aspx

?

Posted by David Haglund @ 01 Jan 2011 1:21 AM
Thanks Josh, just what I was looking for! :)

Posted by Stuart @ 28 Mar 2011 11:49 AM
Thanks for the Bitmap image code. My app wouldn't let me delete a file as it was still being used and this was the solution for that problem.

Thanks again.

Posted by Eric @ 02 Aug 2011 10:15 AM
Ignore last comment - sorted out the static resource stuff.

Worth noting that, if like the situation I have where image may change (updates) but may also be deleted occasionally and so not always guranteed to be present.
In this situation a try catch is needed in the example code e.g.



try
{
if (!string.IsNullOrEmpty(value.ToString()))
{
var bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(value.ToString());
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.EndInit();
return bi;
}
}
catch (Exception) {}

Posted by Øyvind Knobloch-Bråthen @ 20 Oct 2011 11:23 AM
This helped a lot. Had a hard time replacing images that was bound to the WPF GUI, but this did the trick. Thanks a lot.

© 2005 - 2014 Josh Twist - All Rights Reserved.