C# ObjectListView实现树状文件夹浏览
C# ObjectListView 实现树状图与表格显示文件夹内容详解
概述
在C#桌面应用程序开发中,经常需要展示文件系统的树状结构和详细内容。ObjectListView
是一个功能强大的开源.NET控件,它扩展了标准的ListView
控件,提供了更多高级功能。本文将介绍如何使用ObjectListView
实现树状结构显示文件夹内容,并支持图片预览功能。
环境准备
首先,需要通过NuGet安装必要的依赖包:
Install-Package ObjectListView
核心实现
1. 文件系统数据模型
创建一个表示文件系统项的模型类:
public class MyFileSystemInfo : IEquatable<MyFileSystemInfo> {public MyFileSystemInfo(FileSystemInfo fileSystemInfo){if (fileSystemInfo == null) throw new ArgumentNullException("fileSystemInfo");this.info = fileSystemInfo;}public bool IsDirectory { get { return this.AsDirectory != null; } }public DirectoryInfo AsDirectory { get { return info as DirectoryInfo; } }public FileInfo AsFile { get { return info as FileInfo; } }private readonly FileSystemInfo info;public string Name { get { return info.Name; } }public string Extension { get { return info.Extension; } }public DateTime CreationTime { get { return info.CreationTime; } }public DateTime LastWriteTime { get { return info.LastWriteTime; } }public string FullName { get { return info.FullName; } }public FileAttributes Attributes { get { return info.Attributes; } }public long Length { get { return this.AsFile != null ? this.AsFile.Length : 0; } }public IEnumerable GetFileSystemInfos(){ArrayList children = new ArrayList();if (this.IsDirectory){foreach (FileSystemInfo x in this.AsDirectory.GetFileSystemInfos())children.Add(new MyFileSystemInfo(x));}return children;}// 实现相等性比较接口public bool Equals(MyFileSystemInfo other){return other != null && Equals(other.info.FullName, this.info.FullName);}public override bool Equals(object obj){return Equals(obj as MyFileSystemInfo);}public override int GetHashCode(){return this.info.FullName.GetHashCode();} }
2. 初始化树状列表视图
void InitializeTreeListExample() {// 设置树形列表属性this.treeListView.HierarchicalCheckboxes = true;this.treeListView.HideSelection = true;// 设置节点展开判断逻辑this.treeListView.CanExpandGetter = delegate (object x){return ((MyFileSystemInfo)x).IsDirectory;};// 设置获取子节点逻辑this.treeListView.ChildrenGetter = delegate (object x){MyFileSystemInfo myFileSystemInfo = (MyFileSystemInfo)x;try{return myFileSystemInfo.GetFileSystemInfos();}catch (UnauthorizedAccessException ex){MessageBox.Show(ex.Message, "权限错误", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);return new ArrayList();}};// 自定义树形连接线样式TreeListView.TreeRenderer renderer = this.treeListView.TreeColumnRenderer;renderer.LinePen = new Pen(Color.Firebrick, 0.5f);renderer.LinePen.DashStyle = DashStyle.Dot;// 设置系统图标SysImageListHelper helper = new SysImageListHelper(this.treeListView);this.treeColumnName.ImageGetter = delegate (object x){return helper.GetImageIndex(((MyFileSystemInfo)x).FullName);};// 设置自定义渲染器this.treeColumnDetail.Renderer = new OperationRenderer();this.treeColumnDelete.Renderer = new OperationRenderer1();// 设置文件类型列this.treeColumnFileType.AspectGetter = delegate (object x){return ShellUtilities.GetFileType(((MyFileSystemInfo)x).FullName);};// 加载根节点string path = "E://Imgs//" + DateTime.Now.ToString("yyyyMMdd");ArrayList roots = new ArrayList();roots.Add(new MyFileSystemInfo(new DirectoryInfo(path)));this.treeListView.Roots = roots;this.treeListView.Refresh();SelectAllNodes(); // 选中所有节点 }
3. 自定义列渲染器
实现操作按钮的自定义渲染:
public class OperationRenderer : BaseRenderer {private readonly Pen borderPen = new Pen(Color.DarkBlue, 1.5f);private readonly Brush textBrush = new SolidBrush(Color.White);private readonly Brush backgroundBrush = new SolidBrush(Color.FromArgb(70, 130, 180));public override void Render(Graphics g, Rectangle r){var rowData = this.RowObject as MyFileSystemInfo;if (ShouldShowOperation(rowData)){// 绘制按钮背景和边框g.FillRectangle(backgroundBrush, r);g.DrawRectangle(borderPen, r.X, r.Y, r.Width - 1, r.Height - 1);// 绘制文字StringFormat fmt = new StringFormat{Alignment = StringAlignment.Center,LineAlignment = StringAlignment.Center};g.DrawString("详情", new Font("微软雅黑", 9, FontStyle.Bold),textBrush, r, fmt);}else{// 清空不满足条件的单元格using (var clearBrush = new SolidBrush(this.ListView.BackColor)){g.FillRectangle(clearBrush, r);}}}// 条件判断逻辑private bool ShouldShowOperation(MyFileSystemInfo data){return data.IsDirectory && data.Name != DateTime.Now.ToString("yyyyMMdd");} }
4. 图片预览功能
实现点击查看图片详情功能:
private void treeListView_CellClick(object sender, CellClickEventArgs e) {if (e.Column == this.treeColumnDetail){// 获取绑定的文件系统对象var fileInfo = e.Model as MyFileSystemInfo;if (fileInfo == null) return;// 清空现有图片if (images.Count > 0){foreach (var img in images){img.Dispose();}images.Clear();}// 加载新图片imagePaths = GetImageFiles(fileInfo.FullName);images = new List<Image>();LoadImages();// 显示图片for (int i = 0; i < 4; i++){if (images.Count - 1 >= i){DisplayImage(i);}else{pictureBoxeList[i].Image = defaultImage;}}}else if (e.Column == this.treeColumnDelete){// 删除操作var fileInfo = e.Model as MyFileSystemInfo;if (fileInfo == null) return;if (Directory.Exists(fileInfo.FullName)){try{Directory.Delete(fileInfo.FullName, true);}catch (Exception ex){MessageBox.Show($"删除失败: {ex.Message}");}}RefreshTreeView();} }// 获取文件夹中的所有图片文件 static List<string> GetImageFiles(string folderPath) {List<string> imagePaths = new List<string>();if (Directory.Exists(folderPath)){string[] imageExtensions = { "*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.tiff" };foreach (var extension in imageExtensions){string[] files = Directory.GetFiles(folderPath, extension, SearchOption.AllDirectories);imagePaths.AddRange(files);}}return imagePaths; }
5. 搜索功能
实现按名称搜索文件系统项:
private void BtnSearch_Click(object sender, EventArgs e) {ArrayList roots = new ArrayList();string targetPath = "E://Imgs//" + DateTime.Now.ToString("yyyyMMdd");if (string.IsNullOrEmpty(TxtCX.Text)){roots.Add(new MyFileSystemInfo(new DirectoryInfo(targetPath)));this.treeListView.Roots = roots;return;}// 获取所有文件系统项var allEntries = GetAllFileSystemEntries(targetPath);ArrayList filteredResults = new ArrayList();// 筛选匹配项foreach (var entry in allEntries){var myInfo = new MyFileSystemInfo(entry);if (myInfo.Name.Contains(TxtCX.Text)){filteredResults.Add(myInfo);}}// 更新树形视图if (filteredResults.Count > 0){this.treeListView.Roots = filteredResults;}this.treeListView.Refresh(); }// 递归获取所有文件系统项 private List<FileSystemInfo> GetAllFileSystemEntries(string rootPath) {var entries = new List<FileSystemInfo>();try{var rootDir = new DirectoryInfo(rootPath);entries.Add(rootDir);// 递归遍历子目录foreach (var dir in rootDir.EnumerateDirectories("*", SearchOption.AllDirectories)){entries.Add(dir);foreach (var file in dir.EnumerateFiles()){entries.Add(file);}}// 添加根目录文件foreach (var file in rootDir.EnumerateFiles()){entries.Add(file);}}catch (Exception ex){Console.WriteLine($"遍历错误: {ex.Message}");}return entries; }
界面设计建议
布局设计:
使用SplitContainer将界面分为左右两部分
左侧放置TreeListView显示文件树
右侧放置PictureBox数组用于图片预览
列配置:
名称列:显示文件/文件夹名称和系统图标
类型列:显示文件类型描述
修改时间列:显示最后修改时间
大小列:显示文件大小
操作列:放置详情和删除按钮
交互设计:
支持节点展开/折叠
支持复选框多选
支持点击操作按钮执行相应功能
支持搜索过滤
总结
通过使用ObjectListView
控件,我们可以轻松实现一个功能丰富的文件浏览器,具备树形结构展示、多选操作、图片预览等高级功能。本文介绍了核心实现方法,包括数据模型设计、树形列表初始化、自定义渲染器、图片预览和搜索功能。
关键点:
使用
MyFileSystemInfo
类封装文件系统项通过
CanExpandGetter
和ChildrenGetter
实现树形结构自定义渲染器实现操作按钮
递归遍历文件系统实现搜索功能
使用PictureBox数组实现多图预览
这种实现方式可以广泛应用于文件管理、图片浏览、资源管理等场景,具有良好的扩展性和用户体验。
希望本文对您理解和使用C# ObjectListView控件有所帮助。如有任何问题,欢迎在评论区留言讨论