赞
踩
最近,在做一个WPF项目。项目中有一个需求,就是以列表的方式显示出项目图片。这些图片有的存在于互联网上,有的存在于本地磁盘。存在本地磁盘的文件好说,主要是存在于网络的图片。因为存在于网络的图片,在载入时需要耗费时间,如果直接给Image控件绑定URI属性的话,会造成界面卡顿。为了提供更好的体验,要求有类似网页中图片载入中的特效。
经过两天的研究,我翻看了爱壁纸HD For Windows的源代码(你懂得)。终于完成了这个功能。实现的效果如右图所示:
显示图片列表的,肯定是一个ListBox。通过自定义ListBox的ItemsPanel和ItemTemplate,可以实现ListBox的子项横排,以及设置子项为图片。
在做WPF项目时,我们通常是通过绑定为控件的属性赋值,所以我们要先构造一个数据源并且做一个ViewModel。
数据源,就设定为一个简单的文本文件(list.txt)。每行,一个图片地址。
示例代码如下:
在图上,大家可以看到,有一个载入中的效果,我们的下一个任务,就是把这个效果给做出来。(这个,我照搬的。。)
原图片如下:
WPF原生并不支持GIF格式的图片,并且GIF格式的图片色彩也很有限,所以这个载入中效果是PNG图片加旋转动画完成的。首先,我们要添加一个用户控件。这个用户控件中只有一个Image子控件。在XAML文件中,将Image控件的URI设置为此图片,并且在Image的图片载入完成后,开始动画。XAML(WaitingProgress.xaml)代码如下:
接着,咱们就该分析如何获得图片了。因为图片可能存在本地磁盘上,也可能存在网络上,所以需要根据不同的存储位置,使用不同的方法获取图片(PS:如果使用BitmapImage作为图像源,并且通过URI加载图像,那么,在异步设置Image的Source为此图像时,会发生对象不属于此线程的错误{大概就是这个错误。}。这个错误是BitmapImage报错的,并不是Image控件报错的。具体原因,不太了解。)
在效果图中,我们可以看到,这些图片不是一下子全部显示出来的,而是一张接着一张显示出来的。这里,就要用到一个泛型先入先出集合Queue<T>。在为列表绑定源时,将数据加载到Queue集合中。然后,创建一个后台线程,由这个后台线程不断的从集合中取出数据,并且转化为BitmapImage。并且,在转换完成后会通知Image控件,图片我给你下载完成了,你自己看着办吧。当所有图片都下载完成后,这个后台进程也不会停止,而是处于等待状态,只要有新的绑定进来,那么线程就立刻激活,继续干自己该干的事情。这里我们又要用到一个类型:AutoResetEvent。原理,就是这么一个原理,且看代码(ImageQueue.cs)如下:
代码中,我们定义了一个委托和一个事件。通知Image控件的重任,就交给这两元大将了。
接着,我们就来做图片显示列表(ListBox)的效果。我们知道,在Grid控件中,如果一个子控件不设置任何位置或者大小属性的话,这个子控件是会填满这个Grid的。所以我们要自定义ListBox的ItemTemplate。让其包含一个Grid控件。这个Grid控件有两个子控件,一个是刚才做的进度条控件,无定位、大小属性。另一是Image控件,这个控件设置大小属性。
首先,我们先让进度条控件显示出来,接着,为ListBox绑定数据源,同时,把要下载的数据压入下载队列,并且注册下载完成的事件,在事件执行时,将进度条隐藏掉,为Image控件设置Source属性为取到的值并且添加一个渐变动画。
要实现上述功能,我们就需要添加一个依赖属性。
至此,这个Demo就算是做完了。我接触WPF的时间虽然不短,但是真正用的却是不多。这篇文章中用的很多东西,都是在做这个Demo的时候学的,欢迎大家与我交流。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。