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

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

先看下效果图:



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

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

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

首先看到的是Form_Load,它的作用是加载根节点和驱动器列表:
            treeView1.Nodes.Add(new TreeNode("Computer", DriveInfo.GetDrives()
.Select(x => new TreeNode(x.Name) { Tag = x }).ToArray()) { Tag = "root" });

你没有看错,一行就写完了。
如果不用LINQ,我们可以怎么写呢?
            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表达式:
x => new TreeNode(x.Name) { Tag = x }


它相当于你写了这么一个函数:
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操作就可以了。
...全文
6871 111 打赏 收藏 转发到动态 举报
写回复
用AI写文章
111 条回复
切换为时间正序
请发表友善的回复…
发表回复
大鹏灬 2014-11-06
  • 打赏
  • 举报
回复
路过的菜鸟 2014-11-01
  • 打赏
  • 举报
回复
学习,谢谢分享
nongfuxu123 2014-11-01
  • 打赏
  • 举报
回复
好贴,学习中。
kslynn 2013-11-19
  • 打赏
  • 举报
回复
顶. 可以作为学习linq的经典案例. 从中学到了不少好东西. 强烈顶.
vssvss 2013-06-04
  • 打赏
  • 举报
回复
引用 65 楼 jiangshun 的回复:
        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());
            }

        }
支持wmi
lxhlovemy 2013-04-25
  • 打赏
  • 举报
回复
以后会用,标记下
松林迷途 2012-11-14
  • 打赏
  • 举报
回复
最近刚接触linq,很不错,非常优美的代码。
q107770540 2012-11-05
  • 打赏
  • 举报
回复
感谢分享~~
cqhq2008 2012-09-05
  • 打赏
  • 举报
回复
treDirectory.Nodes.AddRange(DriveInfo.GetDrives().Select(x => new TreeNode(x.Name) { Tag = x }).ToArray());这样应该可以吧?
cqhq2008 2012-09-05
  • 打赏
  • 举报
回复
如果不想得到那个根,只要驱动器应该怎样修改代码,谢谢!
cqhq2008 2012-08-26
  • 打赏
  • 举报
回复
好东西,收藏了,感谢分享!
sysun 2012-07-24
  • 打赏
  • 举报
回复
好帖,学习一下。
wzuomin 2012-04-17
  • 打赏
  • 举报
回复
好贴,这个要顶。。。。
小颗豆 2012-04-16
  • 打赏
  • 举报
回复
好贴,标记
港定小河 2012-04-05
  • 打赏
  • 举报
回复
大家集思广益,好贴,收藏!
blackkettle 2012-04-05
  • 打赏
  • 举报
回复
LINQ 好强大!
霹雳三口组 2012-04-03
  • 打赏
  • 举报
回复
好厉害啊,
猴头 2012-04-01
  • 打赏
  • 举报
回复
最近linq的帖子好多啊
alextienpai 2012-04-01
  • 打赏
  • 举报
回复
这个不错!很感激这种拿来分享给新手看的!真的很有用!
寂小魔 2012-03-31
  • 打赏
  • 举报
回复
好贴 必须有个位
·
加载更多回复(53)

110,521

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧