WP7 可以在XAML中使用的 缓存图片控件(适合静态)
首先感谢 kiminozo 分享的代码
可以先看下他的这篇博客:
WP7应用开发笔记 继承BitmapSource并使用独立存储来缓存远程的图片
我修改了下使它可以再XAML中使用
像这样
<Image Margin="5" Width="{Binding imgWidth}" DoubleTap="PleasureListImage_DoubleTap" Stretch="Uniform" MaxWidth="400" > <Image.Source> <StorageCached:StorageCachedImage UriSource="{Binding imgUrl}" /> </Image.Source> </Image>
改造后的代码如下:
View Code
1 /// <summary> 2 /// 独立存储缓存的图片源 3 /// </summary> 4 public sealed class StorageCachedImage : BitmapSource 5 { 6 private Uri uriSource; 7 private string filePath; 8 //缓存目录 9 private const string CacheDirectory = StringResources.TEMP_IMAGE_URL; 10 11 12 public DependencyProperty UriSourceProperty ; 13 14 void UriSourcePropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e) 15 { 16 17 string s = e.NewValue as string; 18 if (s != null) 19 { 20 uriSource = new Uri(s, UriKind.Absolute); 21 Debug.WriteLine(uriSource); 22 //文件路径 23 filePath = Path.Combine(CacheDirectory, uriSource.AbsolutePath.TrimStart('/').Replace('/', '_')); 24 this.OpenCatchSource(); 25 } 26 } 27 28 29 30 public string UriSource 31 { 32 get { return (string)GetValue(UriSourceProperty); } 33 set { SetValue(UriSourceProperty, value); } 34 } 35 36 static StorageCachedImage() 37 { 38 39 //创建缓存目录 40 using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()) 41 { 42 if (!isolatedStorageFile.DirectoryExists(CacheDirectory)) 43 { 44 isolatedStorageFile.CreateDirectory(CacheDirectory); 45 } 46 } 47 } 48 49 /// <summary> 50 /// 创建一个独立存储缓存的图片源 51 /// </summary> 52 /// <param name="uriSource"></param> 53 public StorageCachedImage(Uri uriSource) 54 { 55 uriSource = uriSource; 56 57 //文件路径 58 filePath = Path.Combine(CacheDirectory, uriSource.AbsolutePath.TrimStart('/').Replace('/', '_')); 59 OpenCatchSource(); 60 } 61 62 /// <summary> 63 /// 放在xaml 需要这个构造方法 64 /// </summary> 65 public StorageCachedImage() 66 { 67 UriSourceProperty = 68 DependencyProperty.Register( 69 "UriSource", 70 typeof(string), 71 typeof(StorageCachedImage), 72 new PropertyMetadata(new PropertyChangedCallback(UriSourcePropertyChangedCallback))); 73 74 } 75 76 77 /// <summary> 78 /// 打开缓存源 79 /// </summary> 80 public void OpenCatchSource() 81 { 82 bool exist; 83 using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()) 84 { 85 exist = isolatedStorageFile.FileExists(filePath); 86 } 87 if (exist) 88 { 89 SetCacheStreamSource(); 90 } 91 else 92 { 93 SetWebStreamSource(); 94 } 95 } 96 97 /// <summary> 98 /// 设置缓存流到图片 99 /// </summary> 100 private void SetCacheStreamSource() 101 { 102 using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()) 103 using (var stream = isolatedStorageFile.OpenFile(filePath, FileMode.Open, FileAccess.Read)) 104 { 105 SetSource(stream); 106 } 107 } 108 109 /// <summary> 110 /// 下载Uri中的图片 111 /// </summary> 112 private void SetWebStreamSource() 113 { 114 var httpWebRequest = (HttpWebRequest)WebRequest.Create(uriSource); 115 httpWebRequest.AllowReadStreamBuffering = true; 116 httpWebRequest.BeginGetResponse(ResponseCallBack, httpWebRequest); 117 } 118 119 /// <summary> 120 /// 下载回调 121 /// </summary> 122 /// <param name="asyncResult"></param> 123 private void ResponseCallBack(IAsyncResult asyncResult) 124 { 125 126 var httpWebRequest = asyncResult.AsyncState as HttpWebRequest; 127 if (httpWebRequest == null) return; 128 try 129 { 130 var response = httpWebRequest.EndGetResponse(asyncResult); 131 using (var stream = response.GetResponseStream()) 132 using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()) 133 using (var fileStream = isolatedStorageFile.OpenFile(filePath, FileMode.OpenOrCreate, FileAccess.Write)) 134 { 135 stream.CopyTo(fileStream); 136 } 137 Dispatcher.BeginInvoke(SetCacheStreamSource); 138 } 139 catch (Exception err) 140 { 141 Debug.WriteLine(err.Message); 142 } 143 } 144 }
在XAML中引用
1 xmlns:StorageCached="clr-namespace:类所在的命名空间"
参考 : .Net3.0里的DependencyProperty(1)
建议:适合场景广告或者背景等静态的位置
备注: 这个方法还是有些要注意的地方,这个方法只适合于是用在静态的地方,不会连续要加载图片的地方,如果写在xaml的<list>中不会释放图片,会造成内存泄露,当然 BitmapImage这么用也是一样 , 如果是在代码中new 出的就不会有这些问题
我修改了下 在我的<List> 是这么用的
<List>
....
<Image Source="{Binding img}" />
.....
</List>
vo.img = new StorageCachedImage(uri)