A WPF control that wraps the Image control to enable file-system based caching.
If we use the native WPF Image
control for displaying images over the HTTP protocol (by setting the Source
to an http url), the image will be downloaded from the server every time the control is loaded.
In its Dedicated
mode (see Cache Mode
below), the Image
control present in this CachedImage
library, wraps the native Image
control to add a local file-system based caching capability. This control creates a local copy of the image on the first time an image is downloaded; to a configurable cache folder (defaults to <current-user/appdata/roaming>\AppName\Cache
). All the subsequent loads of the control (or the page, window or app that contains the control), will display the image from the local file-system and will not download it from the server.
In its WinINet
mode, the Image
control uses the Temporary Internet Files directory that IE uses for the cache.
We provide two cache mode: WinINet
mode and Dedicated
mode.
WinINet
: This is the default mode and it takes advantage ofBitmapImage.UriCachePolicy
property and uses the Temporary Internet Files directory of IE to store cached images. The image control will have the same cache policy of IE.Dedicated
: Another url-based cache implementation. You can set your own cache directory. The cache will never expire unless you delete the cache folder manually.
- Install the NuGet package named
CachedImage
on the WPF project - Add a namespace reference to the
CachedImage
assembly on the Window/Usercontrolxmlns:cachedImage="clr-namespace:CachedImage;assembly=CachedImage"
as in the exampleWindow
below:
<Window x:Class="MyWindow1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:cachedImage="clr-namespace:CachedImage;assembly=CachedImage">
</Window>
- Use the control and set or bind the
ImageUrl
attribute:
<cachedImage:Image ImageUrl="{Binding LargeImageUrl}"> </cachedImage:Image>
- As it is only a wrapper, all the XAML elements that could be used with the
Image
control are valid here as well:
<cachedImage:Image ImageUrl="{Binding LargeImageUrl}">
<Image.ToolTip>This image gets cached to the file-system the first time it is downloaded</Image.ToolTip>
</cachedImage:Image>
- To change cache mode, set FileCache.AppCacheMode like this:
CachedImage.FileCache.AppCacheMode = CachedImage.FileCache.CacheMode.Dedicated; // The default mode is WinINet
- To change the cache folder location of the dedicated cache mode, set the static string property named
AppCacheDirectory
of theFileCache
class like this:
CachedImage.FileCache.AppCacheDirectory = string.format("{0}\\MyCustomCacheFolder\\",
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
-
Please note that the dedicated cache mode does not consider
Cache-Control
orExpires
headers. Unless the cache folder (or specific files in it) gets deleted, the control will not fetch the file again from the server. The application could let the end-user empty the cache folder as done in the flickr downloadr application that uses this control. -
If you will be loading arbitrary images from a source outside your control, it may be advisable to set
CreateOptions
toIgnoreColorProfile
. As described by Scott Hanselman here on his blog, without this setting, images that have a corrupt Color Profile will throw anArgumentException
(at System.Windows.Media.ColorContext.GetColorContextsHelper)
<cachedImage:Image CreateOptions="IgnoreColorProfile"> </cachedImage:Image>
All of the code in this library is from the answers on a Stack Overflow question:
How do I cache images on the client for a WPF application?.
Thanks to:
-
Simon Hartcher, who answered his own question with the solution
-
Jeroen van Langen for the wonderful refacoring of Simon's solution
-
Stackie Jia for the enhancement of adding another IE based caching (#5)
-
Ben Morningstar for fixing the low request timeout issue (#15)