using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Text;
using System.IO.IsolatedStorage;
using System.IO;
namespace Cache
{
public class ImageCache : DependencyObject
{
public static readonly DependencyProperty SourceProperty = DependencyProperty.RegisterAttached(
"Source",
typeof(String),
typeof(ImageCache),
new PropertyMetadata(String.Empty, OnSourceChanged)
);
public static void SetSource(DependencyObject source, String value)
{
source.SetValue(SourceProperty, value);
}
public static String GetSource(DependencyObject source)
{
return (String)source.GetValue(SourceProperty);
}
private static void OnSourceChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
{
String value = args.NewValue as String;
if (String.IsNullOrEmpty(value) == true)
{
return;
}
Image image = target as Image;
if (image != null)
{
image.Source = new BitmapWithCacheSource(value);
return;
}
BitmapImage bitmapImage = target as BitmapImage;
if (bitmapImage != null)
{
new BitmapWithCacheSource(value, bitmapImage);
return;
}
}
}
public sealed class BitmapWithCacheSource : BitmapSource
{
private static readonly Encoding UTF8Encoding = Encoding.UTF8;
public const string IMAGECACHEDIRECTORY = "ImagesCache/";
private IsolatedStorageFile _iso = IsolatedStorageFile.GetUserStoreForApplication();
private readonly String _imageWebUrl;
private readonly String _imageCacheFileName;
static BitmapWithCacheSource()
{
String imageCacheDriectory = IMAGECACHEDIRECTORY.TrimEnd('/');
IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication();
if (iso.DirectoryExists(imageCacheDriectory) == false)
{
iso.CreateDirectory(imageCacheDriectory);
}
}
private String ToInternalKey(String value)
{
if (String.IsNullOrEmpty(value))
{
return String.Empty;
}
String exName = value.Substring(value.LastIndexOf('.'));
byte[] bytes = UTF8Encoding.GetBytes(value);
return Convert.ToBase64String(bytes) + exName;
}
public BitmapWithCacheSource(String imageWebUrl) : this(imageWebUrl, null) { }
public BitmapWithCacheSource(String imageWebUrl, BitmapImage bitmapImage)
{
this._imageWebUrl = imageWebUrl;
this._imageCacheFileName = IMAGECACHEDIRECTORY + ToInternalKey(this._imageWebUrl);
this.SetImageStreamSource(bitmapImage);
}
private void SetImageStreamSource(BitmapImage bitmapImage)
{
BitmapSource bitmapSource = this;
if (bitmapImage != null)
{
bitmapSource = bitmapImage;
}
if (_iso.FileExists(this._imageCacheFileName) == true)
{
SetImageCacheStreamSource(bitmapSource);
return;
}
if (bitmapImage == null)
{
SetImageWebStreamSource();
return;
}
bitmapImage.UriSource = new Uri(this._imageWebUrl, UriKind.Absolute);
bitmapImage.ImageOpened += bitmapImage_ImageOpened;
}
private void bitmapImage_ImageOpened(object sender, RoutedEventArgs e)
{
BitmapImage bitmapImage = (BitmapImage)sender;
bitmapImage.ImageOpened -= bitmapImage_ImageOpened;
WriteableBitmap writeableBitmap = new WriteableBitmap(bitmapImage);
using (var fileStream = this._iso.OpenFile(this._imageCacheFileName, FileMode.Create, FileAccess.Write))
{
writeableBitmap.SaveJpeg(fileStream, bitmapImage.PixelWidth, bitmapImage.PixelHeight, 0, 100);
}
}
private void SetImageCacheStreamSource(BitmapSource source)
{
using (var imageStream = this._iso.OpenFile(this._imageCacheFileName, FileMode.Open, FileAccess.Read))
{
source.SetSource(imageStream);
}
}
private void SetImageWebStreamSource()
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(this._imageWebUrl);
httpWebRequest.AllowReadStreamBuffering = true;
httpWebRequest.BeginGetResponse(ResponseCallBack, httpWebRequest);
}
private void ResponseCallBack(IAsyncResult asyncResult)
{
var httpWebRequest = asyncResult.AsyncState as HttpWebRequest;
try
{
var response = httpWebRequest.EndGetResponse(asyncResult);
var stream = response.GetResponseStream();
using (var fileStream = this._iso.OpenFile(this._imageCacheFileName, FileMode.Create, FileAccess.Write))
{
stream.CopyTo(fileStream);
base.Dispatcher.BeginInvoke(() =>
{
stream.Seek(0, SeekOrigin.Begin);
base.SetSource(stream);
stream.Dispose();
});
}
}
catch
{
}
}
}
}
调用方法
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
this.imagesStackPanel.DataContext = "url";
}
private void Button_Click(object sender, RoutedEventArgs e)
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.DownloadProgress += bitmapImage_DownloadProgress;
//使用方式2
Cache.ImageCache.SetSource(bitmapImage,"url");
this.bitmapImageImage.Source = bitmapImage;
}
void bitmapImage_DownloadProgress(object sender, DownloadProgressEventArgs e)
{
this.imageDownloadProgress.Value = e.Progress;
}
前台:
<StackPanel x:Name="imagesStackPanel" xmlns:cache="clr-namespace:Cache" Margin="20"> <!--使用方式1--> <Image cache:ImageCache.Source="{Binding}" MaxHeight="300" /> <Button Content="使用BitmapImage" Click="Button_Click" /> <ProgressBar x:Name="imageDownloadProgress" VerticalAlignment="Top" /> <Image x:Name="bitmapImageImage" MaxHeight="300" /> </StackPanel>
转自:
http://www.cnblogs.com/l_nh/archive/2013/01/25/2876325.html