none
如何转储 Image 控件中的图片?(非获取 Image.Source 然后下载保存) RRS feed

  • 问题

  • 比如有一个 显示网络图片的并能将其保存的应用。应用程序界面排列了大量的 Image 控件,Image 控件的 网络URI,那么应用程序在显示图片时,图片肯定是已经在内存中了,此时如果我需要保存他,选择 HttpClient 下载,那么无疑是 2 次访问图片源(HttpClient 肯定不知道 Image 控件已经“下载”了图片),或许你会说先下载好图片,然后显示本地图片就行了,但如果处于某些不可抗力的因素无法这样实现呢?

    话说回来,Image 显示出了网络图片,那么这个图片肯定存在于内存中了,如何转储它呢?


    2015年11月9日 12:56

全部回复

  • 自己回复下吧,我最后是通过写一个 可缓存 Image 控件 来实现这一功能的,具体代码如下:

    <UserControl x:Class="XXX.Controls.CacheableImageControl"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XXX.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="72" d:DesignWidth="82"> <Image x:Name="Image" /> </UserControl>

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices.WindowsRuntime;
    using System.Threading.Tasks;
    using XXX.Common;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Media.Imaging;
    using Windows.UI.Xaml.Navigation;
    
    // The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
    
    namespace XXX.Controls
    {
        public sealed partial class CacheableImageControl : UserControl
        {
            /// <summary>
            /// 获取或设置图像的源。
            /// </summary>
            public ImageSource Source
            {
                get { return (ImageSource)GetValue(SourceProperty); }
                set { SetValue(SourceProperty, value); }
            }
            // Using a DependencyProperty as the backing store for Source.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty SourceProperty =
                DependencyProperty.Register("Source", typeof(ImageSource), typeof(CacheableImageControl), new PropertyMetadata(null, SourcePropertyChangedCallback));
    
            private static async void SourcePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var cacheableImageControl = (CacheableImageControl)d;
                string imageUri = ((BitmapImage)e.NewValue).UriSource.AbsoluteUri;
    
                if (string.IsNullOrWhiteSpace(imageUri))
                {
                    return;
                }
    
                // 检查 URI 是否为网络 URI。
                if (imageUri.StartsWith("http://"))
                {
                    string cachePath = Path.Combine(cacheableImageControl.CacheDirectory, Path.GetFileName(imageUri));
    
                    // 检查图像是否已缓存。
                    if (!File.Exists(cachePath))
                    {
                        // 设置 “正在加载” 图像。
                        if (cacheableImageControl.LoadingImageUri != null)
                        {
                            cacheableImageControl.Image.Source = new BitmapImage(cacheableImageControl.LoadingImageUri);
                        }
    
                        // 下载图像并检查是否成功。
                        if (!await ApplicationDataManager.DownloadImageAsync(imageUri, cacheableImageControl.CacheDirectory))
                        {
                            // 下载失败则设置 “加载失败” 图像。
                            if (cacheableImageControl.FaildImageUri != null)
                            {
                                cacheableImageControl.Image.Source = new BitmapImage(cacheableImageControl.FaildImageUri);
                            }
                            return;
                        }
                    }
    
                    cacheableImageControl.Image.Source = new BitmapImage(new Uri(cachePath));
                }
                else
                {
                    cacheableImageControl.Image.Source = new BitmapImage(new Uri(imageUri));
                }
            }
    
            /// <summary>
            /// 获取或设置表示 “加载失败” 的图像的 URI。
            /// </summary>
            public Uri FaildImageUri
            {
                get { return (Uri)GetValue(FaildImageUriProperty); }
                set { SetValue(FaildImageUriProperty, value); }
            }
            // Using a DependencyProperty as the backing store for FaildImageUri.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty FaildImageUriProperty =
                DependencyProperty.Register("FaildImageUri", typeof(Uri), typeof(CacheableImageControl), new PropertyMetadata(null));
    
            /// <summary>
            /// 获取或设置表示 “正在加载” 的图像的 URI。
            /// </summary>
            public Uri LoadingImageUri
            {
                get { return (Uri)GetValue(LoadingImageUriProperty); }
                set { SetValue(LoadingImageUriProperty, value); }
            }
            // Using a DependencyProperty as the backing store for LoadingImageUri.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty LoadingImageUriProperty =
                DependencyProperty.Register("LoadingImageUri", typeof(Uri), typeof(CacheableImageControl), new PropertyMetadata(null));
    
            /// <summary>
            /// 获取或设置缓存的目录。
            /// </summary>
            public string CacheDirectory
            {
                get { return (string)GetValue(CachedDirectoryProperty); }
                set { SetValue(CachedDirectoryProperty, value); }
            }
            // Using a DependencyProperty as the backing store for CacheDirectory.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty CachedDirectoryProperty =
                DependencyProperty.Register("CacheDirectory", typeof(string), typeof(CacheableImageControl), new PropertyMetadata(null));
    
    
            public Stretch Stretch
            {
                get { return (Stretch)GetValue(StretchProperty); }
                set { SetValue(StretchProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for Stretch.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty StretchProperty =
                DependencyProperty.Register("Stretch", typeof(Stretch), typeof(CacheableImageControl), new PropertyMetadata(Stretch.Uniform,StretchPropertyChangedCallback));
    
            private static void StretchPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var cacheableImageControl = (CacheableImageControl)d;
                var stretch = (Stretch)e.NewValue;
    
                if (cacheableImageControl.Image != null)
                {
                    cacheableImageControl.Image.Stretch = stretch;
                }
            }
    
            public CacheableImageControl()
            {
                this.InitializeComponent();
            }
        }
    }
    
    上面的实现参考了:【WP8】图片缓存控件

    2015年12月1日 7:01