首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

分享一个简单的资源管理器程序,主要是演示下LINQ在C#开发中的运用解决办法

2012-04-17 
分享一个简单的资源管理器程序,主要是演示下LINQ在C#开发中的运用以前有人在论坛里面问过,如何实现一个类

分享一个简单的资源管理器程序,主要是演示下LINQ在C#开发中的运用
以前有人在论坛里面问过,如何实现一个类似资源管理器的界面,其实运用 System.IO 下的一组API,很容易查询文件系统的文件。虽然说容易,但是还是很多人希望能看到具体的代码。下面我对其中最关键的代码作一个演示,程序尽可能简单,以便大家关注于主要问题。

先看下效果图:



代码下载 http://download.csdn.net/detail/caozhy/4169965。

本程序中使用了LINQ语法,简洁性大家可以自己体会,由于LINQ的运用,程序甚至连一个循环语句都不需要。很多人有一种误解,说到LINQ,就是数据库访问,就是ORM框架,就是转化成SQL执行等等,其实这是对LINQ的误解,我想用这个例子程序说明,LINQ没有那么神秘,它就是C# 3时代的一种简单语法,它可以融入到程序的每个角落。大家可以放心大胆地使用LINQ简化开发,书写紧凑的代码。

说一下这个程序的主要意图:

首先看到的是Form_Load,它的作用是加载根节点和驱动器列表:

C# code
            treeView1.Nodes.Add(new TreeNode("Computer", DriveInfo.GetDrives()                .Select(x => new TreeNode(x.Name) { Tag = x }).ToArray()) { Tag = "root" });

你没有看错,一行就写完了。
如果不用LINQ,我们可以怎么写呢?
C# code
            var rootNode = new TreeNode("Computer") { Tag = "root" };            treeView1.Nodes.Add(rootNode);            foreach (var item in DriveInfo.GetDrives())            {                rootNode.Nodes.Add(new TreeNode(item.Name) { Tag = item });            }

这段代码的作用和上面的LINQ写法作用是等效的。可是明显写的更复杂了。

使用LINQ写法,用到了Select操作符,这个操作才我们的程序中还会反复出现,所以简单介绍下。

很多人用过SQL,知道用select可以从表中选定某几列,在数学上,这个操作叫投影,通俗地说,就是对集合中的每一个元素做这样一种变换(什么变换由select子句决定),让每个元素成为另一种类型的元素,得到一个新的集合。

从数据中选择几列只是select操作的特例,在LINQ中,Select操作可以方便地将某个类型转换成另一个类型,在这里我们把查询出来的DriveInfo类型对象转换为Nodes.Add()方法理解的TreeNode类型。为此我们使用了一个Lambda表达式:
C# code
x => new TreeNode(x.Name) { Tag = x }


它相当于你写了这么一个函数:
C# code
TreeNode ConvertDriveInfoToTreeNode(DriveInfo x){    TreeNode tn = new TreeNode(x.Name);    tn.Tag = x;    return tn;}


这个函数由谁调用呢?由LINQ调用,而不是你,虽然它是你定义的。

你将函数作为参数传给LINQ,LINQ通过反过来调用你的函数实现这种转换,再提供给你转换后的集合。

之后看到的是treeView1_BeforeExpand事件,它的作用是在展开节点的时候加载下面每个子节点再下一层的节点,为什么要子节点再下一层呢?这样可以让那些包含再下一层元素的节点提前出现“+”号,在展开的时候可以看到。这种按需加载TreeNode的技术很常用,希望新手们熟练掌握。

然后我们看到的是另一个事件处理函数treeView1_AfterSelect,它的作用是在点了某个节点的时候在ListView里面加载这个文件夹下的文件夹和文件。按照Windows习惯,先显示文件夹再显示文件。而且分别对文件夹和文件排序。请问这个如何实现?

如果用LINQ同样简单,只需要使用OrderBy操作就可以了。

[解决办法]
就这么点代码?
[解决办法]
喜欢,以后参考一下

[解决办法]

[解决办法]



放一下源码下载的地址。。。

在帖子中看看有点累
[解决办法]
看源码,最近正在学LINQ

[解决办法]
Linq让代码简化思路清晰。。。好东西
[解决办法]
支持!!!!!!!!!
[解决办法]
学习了,知识因分享而伟大!谢谢楼主!!!
[解决办法]
好,晒晒更进步
[解决办法]
加强学习
[解决办法]
都先进啊,俺还在用2008
[解决办法]


又见linq,是好工具
[解决办法]
很耐心。
[解决办法]

探讨
很耐心。

[解决办法]
谢谢分享,Linq
[解决办法]
學習.thanks!
[解决办法]
非常好,学习一下~
[解决办法]
如果wpf+binding代码会更赞,改天写一个赞助老大
[解决办法]
探讨

引用:
放一下源码下载的地址。。。

在帖子中看看有点累

已经更新代码下载地址。

[解决办法]
感谢 分享
[解决办法]
确实比较牛
[解决办法]
coooooooooooooooool~
[解决办法]
呵呵,linq用了就上瘾,赞了
[解决办法]
尝试用WPF写了一下,比预期的时间多了1个小时,呵呵

逻辑代码:
C# code
public class Drives : List<Drive> {    public Drives() {        this.AddRange(DriveInfo.GetDrives().Where(p => p.IsReady).Select(p => new Drive(p)));    }}public interface Subject {    string Name { get; set; }    string Path { get; set; }}public class File : Subject {    public FileInfo Info { get; set; }    public string Name { get; set; }    public string Path { get; set; }    public File(string arg) : this(new FileInfo(arg)) { }    public File(FileInfo arg) {        this.Path = arg.FullName;        this.Name = System.IO.Path.GetFileName(this.Path);    }}public abstract class FileGroup : Subject {    public string Name { get; set; }    public string Path { get; set; }    public FileGroup() { }    public FileGroup(string name) { this.Name = name; }    public IEnumerable<Subject> Folders {        get { return LoadChildren().OfType<Folder>(); }    }    public IEnumerable<Subject> Children {        get { return LoadChildren(); }    }    protected virtual IEnumerable<Subject> LoadChildren() {        if (children == null) {            var target = new DirectoryInfo(Path);            Func<FileSystemInfo, bool> filter = p => !(                p.Attributes.HasFlag(FileAttributes.System) ||                p.Attributes.HasFlag(FileAttributes.Hidden)            );            var q = target.GetDirectories()                .Where(filter)                .Select(p => new Folder(p as DirectoryInfo)).Concat(                    target.GetFiles()                        .Where(filter)                        .Select(p => new File(p as FileInfo))                        as IEnumerable<Subject>            );            return q;        }        return children;    }    protected IEnumerable<Subject> children = null;}public class Drive : FileGroup {    public DriveInfo Info { get; set; }    public Drive(DriveInfo arg) {        this.Info = arg;        this.Path = arg.RootDirectory.Name;        this.Name = string.Format("{0} ({1})", arg.VolumeLabel, arg.Name);    }}public class Folder : FileGroup {    public DirectoryInfo Info { get; set; }    public Folder(string arg) : this(new DirectoryInfo(arg)) { }    public Folder(DirectoryInfo arg) {        this.Info = arg;        this.Path = arg.FullName;        this.Name = arg.Name;    }}
------解决方案--------------------


纠正:
FileGroup.LoadChildren中
return q;
改为
children = q.ToList();
[解决办法]
不懂这个呢。
[解决办法]
看来我还得继续修炼,惭愧ing
[解决办法]
WPF的树好难看,怎么让树显示前面的引导线?
[解决办法]
看来要好好看看LINQ了。
[解决办法]

探讨

WPF的树好难看,怎么让树显示前面的引导线?

[解决办法]
探讨
引用:

WPF的树好难看,怎么让树显示前面的引导线?


这个可以Style,嘿嘿
详解如何打造Aero风格的TreeView
其实这是优点来的...

[解决办法]
直接写Style就OK了,效果如下,

直接拿来用就行,Show TreeView nodes connected with dotted lines
[解决办法]
代码是简明了,不过调试呢?好像没有传统方式方便吧,特别是单步跟踪,这个有点感觉不是很爽。
[解决办法]
先要搞明白但不跟踪那些范围的代码。设计师是不去跟踪什么代码的,交互设计有交互设计的诀窍。设计师使用 blend,而不是写代码。
[解决办法]
比如说这里的例子非常直接地调用一下控件就轻松完成了,因为界面调整就是调整一下样式。到底只有哪几条代码需要单步跟踪,这其实只要耐心看一下就能明白了。
[解决办法]
额啊。 linq还是不错的……
[解决办法]
C# code
        private void Form1_Load(object sender, EventArgs e)        {            treeView1.Nodes.Add(new TreeNode("Computer",                (new ManagementObjectSearcher("select * from Win32_LogicalDisk").Get().Cast<ManagementObject>().Select(m =>                    new TreeNode(m["DeviceID"] + "") { Name = m["DeviceID"].ToString()+"\\", Tag =  m["CreationClassName"].ToString() }).ToArray())) { Tag = "Root" });        }        private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)        {            e.Node.Nodes.Cast<TreeNode>().ToList().ForEach(x =>            {                try                {                    if (x.Nodes.Count == 0)                    {                        TreeNode[] nodes = new TreeNode[] { };                        string drive = x.Name.Substring(0, 2);                        string path = x.Name.Replace(drive, "").Replace("\\","\\\\");                        if (x.Tag.ToString() == "Win32_LogicalDisk" || x.Tag.ToString() == "File Folder")                        {                            string queryTxt = @"select * from  Win32_Directory where drive=""" + drive + @""" and path=""" + path + @"""";                            nodes = new ManagementObjectSearcher(queryTxt).                                Get().Cast<ManagementObject>().                                Select(m => new TreeNode(m["FileName"].ToString()) { Name = m["name"].ToString() + "\\", Tag = m["FileType"].ToString() }).ToArray();                        }                        x.Nodes.AddRange(nodes);                    }                }                catch { }            });        }        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)        {            if (e.Node.Text == "Computer")            {                listView1.Items.Clear();                listView1.Items.AddRange(new ManagementObjectSearcher("select * from Win32_LogicalDisk").Get().Cast<ManagementObject>().Select(m =>new ListViewItem(new string[]{                                m["name"].ToString(),                                m["Description"].ToString(),                                (Convert.ToInt64(m["Size"])/ 1048576 / 1024).ToString()+"GB",                                ""})).ToArray());            }            if (e.Node.Tag.ToString() == "Win32_LogicalDisk" || e.Node.Tag.ToString() == "File Folder")            {                listView1.Items.Clear();                string drive = e.Node.Name.Substring(0, 2);                string path = e.Node.Name.Replace(drive, "").Replace("\\", "\\\\");                string queryText = @"select * from  CIM_LogicalFile where drive=""" + drive + @""" and path=""" + path + @"""";                listView1.Items.AddRange(new ManagementObjectSearcher(queryText).                                Get().Cast<ManagementObject>().Select(m => new ListViewItem(new string[]{                                m["FileName"].ToString(),                                m["FileType"]+"",                                (Convert.ToInt64(m["FileSize"])/1024).ToString()+"KB",                                m["CreationDate"]+""})).ToArray());            }        } 


[解决办法]
碰到个问题,treeView1_BeforeExpand在展开节点的时候假如磁盘类型是可移动存储设备,并且驱动器未准备好的情况下,处理这个节点会花费相当多的时间

C# code
        private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)        {            e.Node.Nodes.Cast<TreeNode>().ToList().ForEach(x =>                {                    try                    {                        if (x.Nodes.Count == 0)                        {                            TreeNode[] nodes = new TreeNode[] { };                            if (x.Tag.GetType() == typeof(DriveInfo))                            {                                var item = x.Tag as DriveInfo;                                if (item.DriveType == DriveType.Removable && item.IsReady == false)                                {                                    string message = "磁盘类型是可移动存储设备,并且驱动器未准备好会花费相当多的时间";                                }                                nodes = Directory.GetDirectories(item.Name)                                    .Select(y => new DirectoryInfo(y))                                    .Select(y => new TreeNode(y.Name) { Tag = y })                                    .ToArray();                            }                            if (x.Tag.GetType() == typeof(DirectoryInfo))                            {                                var item = x.Tag as DirectoryInfo;                                nodes = Directory.GetDirectories(item.FullName)                                    .Select(y => new DirectoryInfo(y))                                    .Select(y => new TreeNode(y.Name) { Tag = y })                                    .ToArray();                            }                            x.Nodes.AddRange(nodes);                        }                    }                    catch { }                });        } 

热点排行