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

代码下载 http://download.****.net/detail/caozhy/4169965。
本程序中使用了LINQ语法,简洁性大家可以自己体会,由于LINQ的运用,程序甚至连一个循环语句都不需要。很多人有一种误解,说到LINQ,就是数据库访问,就是ORM框架,就是转化成SQL执行等等,其实这是对LINQ的误解,我想用这个例子程序说明,LINQ没有那么神秘,它就是C# 3时代的一种简单语法,它可以融入到程序的每个角落。大家可以放心大胆地使用LINQ简化开发,书写紧凑的代码。
说一下这个程序的主要意图:
首先看到的是Form_Load,它的作用是加载根节点和驱动器列表:
你没有看错,一行就写完了。
如果不用LINQ,我们可以怎么写呢?
这段代码的作用和上面的LINQ写法作用是等效的。可是明显写的更复杂了。
使用LINQ写法,用到了Select操作符,这个操作才我们的程序中还会反复出现,所以简单介绍下。
很多人用过SQL,知道用select可以从表中选定某几列,在数学上,这个操作叫投影,通俗地说,就是对集合中的每一个元素做这样一种变换(什么变换由select子句决定),让每个元素成为另一种类型的元素,得到一个新的集合。
从数据中选择几列只是select操作的特例,在LINQ中,Select操作可以方便地将某个类型转换成另一个类型,在这里我们把查询出来的DriveInfo类型对象转换为Nodes.Add()方法理解的TreeNode类型。为此我们使用了一个Lambda表达式:
它相当于你写了这么一个函数:
这个函数由谁调用呢?由LINQ调用,而不是你,虽然它是你定义的。
你将函数作为参数传给LINQ,LINQ通过反过来调用你的函数实现这种转换,再提供给你转换后的集合。
之后看到的是treeView1_BeforeExpand事件,它的作用是在展开节点的时候加载下面每个子节点再下一层的节点,为什么要子节点再下一层呢?这样可以让那些包含再下一层元素的节点提前出现“+”号,在展开的时候可以看到。这种按需加载TreeNode的技术很常用,希望新手们熟练掌握。
然后我们看到的是另一个事件处理函数treeView1_AfterSelect,它的作用是在点了某个节点的时候在ListView里面加载这个文件夹下的文件夹和文件。按照Windows习惯,先显示文件夹再显示文件。而且分别对文件夹和文件排序。请问这个如何实现?
如果用LINQ同样简单,只需要使用OrderBy操作就可以了。
------解决思路----------------------
就这么点代码?
------解决思路----------------------
喜欢,以后参考一下
------解决思路----------------------

------解决思路----------------------

放一下源码下载的地址。。。
在帖子中看看有点累
------解决思路----------------------
看源码,最近正在学LINQ

------解决思路----------------------
Linq让代码简化思路清晰。。。好东西
------解决思路----------------------
支持!!!!!!!!!
------解决思路----------------------
学习了,知识因分享而伟大!谢谢楼主!!!
------解决思路----------------------
好,晒晒更进步
------解决思路----------------------
加强学习
------解决思路----------------------
都先进啊,俺还在用2008
------解决思路----------------------
又见linq,是好工具
------解决思路----------------------
很耐心。
------解决思路----------------------
.
------解决思路----------------------
谢谢分享,Linq
------解决思路----------------------
學習.thanks!
------解决思路----------------------
非常好,学习一下~
------解决思路----------------------
如果wpf+binding代码会更赞,改天写一个赞助老大
------解决思路----------------------
下下来看了。。。
------解决思路----------------------
感谢 分享
------解决思路----------------------
确实比较牛
------解决思路----------------------
coooooooooooooooool~
------解决思路----------------------
呵呵,linq用了就上瘾,赞了
------解决思路----------------------
尝试用WPF写了一下,比预期的时间多了1个小时,呵呵

逻辑代码:
前台XAML
110行代码,搞定UI和逻辑
代码下载 http://nonocast.cn/?p=3041
------解决思路----------------------
纠正:
FileGroup.LoadChildren中
return q;
改为
children = q.ToList();
------解决思路----------------------
不懂这个呢。
------解决思路----------------------
看来我还得继续修炼,惭愧ing
------解决思路----------------------
WPF的树好难看,怎么让树显示前面的引导线?
------解决思路----------------------
看来要好好看看LINQ了。
------解决思路----------------------
这个可以Style,嘿嘿
详解如何打造Aero风格的TreeView
其实这是优点来的...
以前有人在论坛里面问过,如何实现一个类似资源管理器的界面,其实运用 System.IO 下的一组API,很容易查询文件系统的文件。虽然说容易,但是还是很多人希望能看到具体的代码。下面我对其中最关键的代码作一个演示,程序尽可能简单,以便大家关注于主要问题。
先看下效果图:
代码下载 http://download.****.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操作就可以了。
------解决思路----------------------
就这么点代码?
------解决思路----------------------
喜欢,以后参考一下
------解决思路----------------------
------解决思路----------------------
放一下源码下载的地址。。。
在帖子中看看有点累
------解决思路----------------------
看源码,最近正在学LINQ
------解决思路----------------------
Linq让代码简化思路清晰。。。好东西
------解决思路----------------------
支持!!!!!!!!!
------解决思路----------------------
学习了,知识因分享而伟大!谢谢楼主!!!
------解决思路----------------------
好,晒晒更进步
------解决思路----------------------
加强学习
------解决思路----------------------
都先进啊,俺还在用2008
------解决思路----------------------
又见linq,是好工具
------解决思路----------------------
很耐心。
------解决思路----------------------
.
------解决思路----------------------
谢谢分享,Linq
------解决思路----------------------
學習.thanks!
------解决思路----------------------
非常好,学习一下~
------解决思路----------------------
如果wpf+binding代码会更赞,改天写一个赞助老大
------解决思路----------------------
下下来看了。。。
------解决思路----------------------
感谢 分享
------解决思路----------------------
确实比较牛
------解决思路----------------------
coooooooooooooooool~
------解决思路----------------------
呵呵,linq用了就上瘾,赞了
------解决思路----------------------
尝试用WPF写了一下,比预期的时间多了1个小时,呵呵
逻辑代码:
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;
}
}
前台XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:biz="clr-namespace:Finder.Business"
Title="Finder" Height="500" Width="800">
<Window.Resources>
<biz:Drives x:Key="drivers" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TreeView x:Name="treeViewDir" HorizontalAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{StaticResource drivers}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Folders}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<GridSplitter Width="4" />
<ListView Grid.Column="2" ItemsSource="{Binding ElementName=treeViewDir, Path=SelectedValue.Children}"/>
</Grid>
</Window>
110行代码,搞定UI和逻辑
代码下载 http://nonocast.cn/?p=3041
------解决思路----------------------
纠正:
FileGroup.LoadChildren中
return q;
改为
children = q.ToList();
------解决思路----------------------
不懂这个呢。
------解决思路----------------------
看来我还得继续修炼,惭愧ing
------解决思路----------------------
WPF的树好难看,怎么让树显示前面的引导线?
------解决思路----------------------
看来要好好看看LINQ了。
------解决思路----------------------
这个可以Style,嘿嘿
详解如何打造Aero风格的TreeView
其实这是优点来的...