通过改变ListView控件的ItemsControl.ItemContainerStyle样式可以实现各式各样的列表展示效果。如果后台读取文件夹图片资源后最后给ListView的ItemsSource赋值,可以在前台显示加载的图片列表,但是由于加载图片需要时间,会有一段空白停顿,并且要加载的图片越大停顿的时间越长。如下图所示:
这里的解决方案是首先异步加载图片地址,再异步读取图片资源的方式来加载本地图片列表。效果如下:
具体代码:
1、自定义控件ucListPicView.xaml
2、自定义控件后台代码ucListPicView.xaml.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace ListViewDemo
{
///
/// ucListPicView.xaml 的交互逻辑
///
public partial class ucListPicView : ListView
{
private BackgroundWorker loadLocalBackgroudworker = null;//后台处理线程
private ObservableCollection bindItems = null;// 绑定的资源元素集合
private int nameLargeLength;//可展示的图片名称字数
public int NameLargeLength
{
get
{
return nameLargeLength;
}
set
{
nameLargeLength = value;
}
}
private string itemSourcePath;//图片路径
public string ItemSourcePath
{
get
{
return itemSourcePath;
}
set
{
itemSourcePath = value;
LoadLocalImageData();
}
}
public ucListPicView()
{
InitializeComponent();
bindItems = new ObservableCollection();
}
#region 后台线程处理图片数据
private void LoadLocalImageData()
{
this.ItemsSource = null;
bindItems.Clear();
if (loadLocalBackgroudworker != null)
{
loadLocalBackgroudworker.CancelAsync();
loadLocalBackgroudworker.DoWork -= loadLocalBackgroudworker_DoWork;
loadLocalBackgroudworker.RunWorkerCompleted -= loadLocalBackgroudworker_RunWorkerCompleted;
}
loadLocalBackgroudworker = new BackgroundWorker();
loadLocalBackgroudworker.WorkerSupportsCancellation = true;
loadLocalBackgroudworker.DoWork += loadLocalBackgroudworker_DoWork;
loadLocalBackgroudworker.RunWorkerCompleted += loadLocalBackgroudworker_RunWorkerCompleted;
loadLocalBackgroudworker.RunWorkerAsync();
}
///
/// 逐个加载图片资源
///
private void loadLocalBackgroudworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.ItemsSource = bindItems;
int tempCount = bindItems.Count;
for (int i = 0; i < bindItems.Count; i++)
{
if (tempCount != bindItems.Count)
{
break;
}
LoadImageDataByBackground(bindItems[i]);
}
}
///
/// 加载资源路径
///
private void loadLocalBackgroudworker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
DirectoryInfo theFolder = new DirectoryInfo(ItemSourcePath);
if (!theFolder.Exists)
return;
string[] files = Directory.GetFiles(ItemSourcePath);
if (files.Length > 0)
Array.Sort(files);
for (int i = 0; i < files.Length; i++)
{
this.Dispatcher.Invoke(new Action(() =>
{
if (IsSupport(files[i]))
{
var tmpBindData = new ListBindData();
tmpBindData.ItemName = SetStringLength(GetFileNameEx(files[i]), nameLargeLength);
tmpBindData.ItemPath = files[i];
tmpBindData.ItemWidth = 160;
tmpBindData.ItemHeight = 80;
bindItems.Add(tmpBindData);
}
}));
}
}
catch (Exception ex)
{
}
}
///
/// 加载资源图片线程
///
private void LoadImageDataByBackground(ListBindData bindData)
{
BackgroundWorker loadImgWorker = new BackgroundWorker();
loadImgWorker.DoWork += loadImgWorker_DoWork;
loadImgWorker.RunWorkerCompleted += loadImgWorker_RunWorkerCompleted;
loadImgWorker.WorkerSupportsCancellation = true;
loadImgWorker.RunWorkerAsync(bindData);
}
///
/// 后台线程完成后释放所占资源
///
private void loadImgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
var tempWorker = sender as BackgroundWorker;
if (tempWorker != null)
{
tempWorker.Dispose();
tempWorker = null;
}
}
///
/// 更新资源图片
///
private void loadImgWorker_DoWork(object sender, DoWorkEventArgs e)
{
var bindData = e.Argument as ListBindData;
if (bindData != null)
{
var temp = this.Dispatcher.BeginInvoke(new Action((tempData) =>
{
if (tempData != null && !string.IsNullOrEmpty(tempData.ItemPath))
{
BitmapImage bi = LoadBitmapSourceByPath(tempData.ItemPath);
if (bi != null)
{
tempData.ItemPic = bi;
if (bi.PixelWidth < tempData.ItemWidth && bi.PixelHeight < tempData.ItemHeight)
{
tempData.StrethMethod = Stretch.None;
}
else
{
tempData.StrethMethod = Stretch.UniformToFill;
}
}
bi = null;
}
}), DispatcherPriority.Background, bindData);
}
}
#endregion
#region 辅助方法
///
/// 设置显示的图片名称
///
private string SetStringLength(string text, int leng)
{
if (text.Length > leng)
{
text = text.Substring(0, leng) + "...";
return text;
}
else
{
return text;
}
}
///
/// 从文件路径中获取文件名
///
private static String GetFileName(String fileName)
{
if (fileName == null || fileName == "")
return "";
return fileName.Substring(fileName.LastIndexOf("\\") + 1);
}
///
/// 获得文件后缀名
///
private static String GetEndFile(String fileName)
{
return fileName.Substring(fileName.LastIndexOf(".") + 1);
}
///
/// 获得没有后缀的文件名
///
private static string GetFileNameEx(String fileName)
{
try
{
return GetFileName(fileName).Substring(0, GetFileName(fileName).LastIndexOf(GetEndFile(fileName)) - 1);
}
catch { return ""; }
}
///
/// 文件头转换
///
private enum FileExtension
{
JPG = 255216,
GIF = 7173,
PNG = 13780,
SWF = 6787,
RAR = 8297,
ZIP = 8075,
_7Z = 55122,
VALIDFILE = 9999999
}
///
/// 根据图源属性获取扩展名
///
private string GetBitmapExtensions(string path)
{
try
{
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
string fileType = string.Empty;
FileExtension extension;
using (BinaryReader br = new System.IO.BinaryReader(fs))
{
byte data = br.ReadByte();
fileType += data.ToString();
data = br.ReadByte();
fileType += data.ToString();
try
{
extension = (FileExtension)Enum.Parse(typeof(FileExtension), fileType);
}
catch
{
extension = FileExtension.VALIDFILE;
}
}
return extension.ToString();
}
}
catch (Exception)
{
return FileExtension.VALIDFILE.ToString();
}
}
///
/// 受支持的图片格式
///
private List supportedPicType = new List()
{
"jpg",
"png",
"bmp",
};
///
/// 判断该扩展名是否是受支持的图片类型
///
private bool IsBmpSupport(string ext)
{
return supportedPicType.FindAll((c) => c.Contains(ext.ToLower())).Count > 0;
}
///
/// 判断该图片是否受支持
///
private bool IsSupport(string path)
{
return IsBmpSupport(GetBitmapExtensions(path));
}
///
/// 从指定路径读取图片源
///
private BitmapImage LoadBitmapSourceByPath(string path)
{
try
{
//文件不存在,返回空
if (!File.Exists(path))
{
return null;
}
BitmapImage bi = new BitmapImage();
using (FileStream strream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(strream))
{
byte[] bytes = br.ReadBytes((int)strream.Length);
bi.BeginInit();
bi.StreamSource = new MemoryStream(bytes);
bi.EndInit();
}
}
return bi;
}
catch (Exception ex)
{
return null;
}
}
#endregion
}
public class ListBindData : INotifyPropertyChanged
{
public ListBindData()
{
}
private ImageSource itemPic;
private Stretch strethmethod = Stretch.Uniform;
///
/// 素材展示预览图
///
public ImageSource ItemPic
{
get
{
return itemPic;
}
set
{
if (itemPic != value)
{
itemPic = value;
OnPropertyChanged("ItemPic");
}
}
}
public Stretch StrethMethod
{
get
{
return strethmethod;
}
set
{
if (strethmethod != value)
{
strethmethod = value;
OnPropertyChanged("StrethMethod");
}
}
}
///
/// 图片名称
///
public string ItemName
{
get;
set;
}
///
/// 图片的本地路径
///
public string ItemPath
{
get;
set;
}
///
/// 图片的宽
///
public int ItemWidth
{
get;
set;
}
///
/// 图片的高
///
public int ItemHeight
{
get;
set;
}
private void OnPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
3、主窗体MainWindow.xaml
4、主窗体后台代码
using System;
using System.Windows;
using System.Windows.Forms;
namespace ListViewDemo
{
///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnOpenFile_Click(object sender, RoutedEventArgs e)
{
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
folderBrowserDialog.Description = "选择图片所在的文件夹";
folderBrowserDialog.ShowNewFolderButton = false;
folderBrowserDialog.RootFolder = Environment.SpecialFolder.MyComputer;//设置目录,可注掉
folderBrowserDialog.ShowDialog();
if (folderBrowserDialog.SelectedPath == string.Empty)
{
return;
}
string selectFolder = folderBrowserDialog.SelectedPath;
this.picListView.NameLargeLength = 20;
this.picListView.ItemSourcePath = selectFolder;
}
}
}