当我们上网查看一个较大的图片时,浏览器能一边下载一边显示,这样用户体验是比较好的,但在WPF程序中,当我们通过如下方式显示一幅图片时:
img.Source = new BitmapImage(new Uri("http://localhost:8000/www/test.jpg"));
只能等到图片下载完成时才能显示出来,当图片较大时需要等待很久,即使在旁边放个进度条给人的感觉仍然不好。
今天试了一下,这个效果还算比较容易实现的:在下载过程中,每隔一秒钟(也可以改成按下载进度)将当前下载的所有内容生成一个临时图片,将控件显示为临时文件即可。
代码如下:
{
InitializeComponent();
DownloadImage();
}
async void DownloadImage()
{
var request = WebRequest.Create("http://localhost:8000/www/test.jpg");
using (var response = await request.GetResponseAsync())
using (var destStream = new MemoryStream())
{
var responseStream = response.GetResponseStream();
var downloadTask = responseStream.CopyToAsync(destStream);
RefreshUI(downloadTask, destStream);
await downloadTask;
}
}
async void RefreshUI(Task downloadTask, MemoryStream stream)
{
await Task.WhenAny(downloadTask, Task.Delay(1000)); //每隔一秒刷新一次
var data = stream.ToArray();
var tmpStream = new MemoryStream(data); //TODO 当图片的头没有下载到时,这儿可能抛异常
var bmp = new BitmapImage();
bmp.BeginInit();
bmp.StreamSource = tmpStream;
bmp.EndInit();
img.Source = bmp; //刷新图片
if (!downloadTask.IsCompleted)
RefreshUI(downloadTask, stream, contentLength);
}