ASP.net 2.0包含了很多的Web控件,比如TreeView。它被设计来显示具有层次结构的数据。TreeView可以绑定到一个层次结构数据源,比如XMLDataSource 或 SiteMapDataSource,当然也可以编程来构建.对于用TreeView绑定到SiteMapDataSource以展示一个网站地图的示例,可参见系列文章《Examining ASP.NET2.0's Site Navigation》(http://aspnet.4guysfromrolla.com/articles/111605-1.aspx)
常见的层次结构数据是web server的文件系统file system.在很多情况下,可能有某个文件夹,里面包含了我们要浏览的很多文件以及次级文件夹.通过命名空间System.IO里的类, 我们可以通过编程来用website的目录体系来填充TreeView控件,当用户点击一个文件夹时,就显示该文件夹下的文件.
图1
在本文,我们将考察如何创建一个简单的图片展示页面.我们将用到2个控件:TreeView,它用来展示文件体系;而DataList控件用来展示某个文件夹里的图片.
Displaying the TreeView
在本示例,我们将创建2个部分:
.一个TreeView控件:列出某个指定节点下的文件夹
.一个data Web控件:用于列出某个选定文件夹下的文件.就本文而言,我们使用的是DataList,不过在某些情况下,可能用GridView, DetailsView, FormView,Repeater控件可能更好一些.
让我们开始编程创建TreeView.对ASP.NET 2.0 TreeView的数据,我们可以“显式”(通过一个XMLDataSource 或 SiteMapDataSource)或通过编程来赋值.由于没有内置的返回目录信息的控件可利用,因此我们需要通过编程对TreeView绑定数据.具体来说,我们需要获取某个根目录的信息,接下来才是次级目录.对包含的文件夹,向TreeView添加一个TreeNode节点.
.net Framework包含了很多的类来处理file system;这些类都包含在System.IO命名空间里.比如类DirectoryInfo, 它包含返回指定目录的子目录的方法(GetDirectories()),当然还有返回指定目录下所有文件的方法(GetFiles()).
如下的代码里,我们用某个根目录下的文件层次结构对ID为PictureTree的TreeView控件进行填充,而根目录由常量VirtualImageRoot来指定.代码里使用的AddNodeAndDescendents方法对文件体系进行递归操作(recurse)(对递归的更多详情,请参阅我以前的文章《Recursion, Why It's Cool》(http://www.4guysfromrolla.com/Webtech/060299-2.shtml))
Private Const VirtualImageRoot = "~/Images/Public/"
Private Sub PopulateTree()
'Populate the tree based on the subfolders of the specified VirtualImageRoot
Dim rootFolder As New DirectoryInfo(Server.MapPath(VirtualImageRoot))
Dim root As TreeNode = AddNodeAndDescendents(rootFolder, Nothing)
'Add the root to the TreeView
PictureTree.Nodes.Add(root)
End Sub
Private Function AddNodeAndDescendents(ByVal folder As DirectoryInfo, ByVal parentNode As
TreeNode) As TreeNode
'Add the TreeNode, displaying the folder's name and storing the full path to the folder as
the value...
Dim virtualFoldERPath As String
If parentNode Is Nothing Then
virtualFolderPath = VirtualImageRoot
Else
virtualFolderPath = parentNode.Value & folder.Name & "/"
End If
Dim node As New TreeNode(folder.Name, virtualFolderPath)
'Recurse through this folder's subfolders
Dim subFolders As DirectoryInfo() = folder.GetDirectories()
For Each subFolder As DirectoryInfo In subFolders
Dim child As TreeNode = AddNodeAndDescendents(subFolder, node)
node.ChildNodes.Add(child)
Next
Return node 'Return the new TreeNode
End Function
每个节点都被赋予了一个display value值和一个hidden value值.该display value值是在树形结构里要显示出来的;而hidden value值是要贯穿postbacks,并与该节点的额外信息有所关联的值.这2个值在TreeNode构造函数里指定的——Dim node As New TreeNode(text, value). 其text就是文件夹的名称,而value就是文件夹的相对路径(virtual path).比如-/Images/Public/Picture1.jpg.当然,相对于物理路径(physical path),该相对路径可能就变成了C:MySitesImageGalleryImagesPublicPicture1.jpg. 关于virtual paths 和 physical paths的区别以及如何将virtual paths转换成physical paths的更多信息请看文章《Using Server.MapPath》(http://www.4guysfromrolla.com/Webtech/121799-1.shtml)
显示选定文件夹里的文件
在TreeView里显示文件系统体系之后,剩下的事情就是显示选定文件夹里的文件.为此,我们要在页面里添加一个data Web控件,将其绑定到当前选定文件夹里的文件列表.但是我们如何才知道哪个文件夹被选中了,以及怎么知道用户什么时候想查看另一个文件夹里的文件呢?
TreeView有一个SelectedValue属性,它返回当前选中节点的value,记得我们已经将文件夹的相对路径赋值给相应节点的value.有了选定文件夹的路径,要获取该文件夹里的文件列表,我们可以创建一个DirectoryInfo object对象,并使用其GetFiles()方法,该方法返回一批FileInfo objects对象,然后将其绑定到data Web控件(就本文而言,我们使用一个DataList控件).
当点击TreeView的一个节点时,接着将发生一个postback,并触发TreeView的 SelectedNodeChanged event事件.此时,我们将刚选定的文件夹里的数据重新绑定到data Web控件里.
上述功能可以用下面的代码来实现.DisplayPicturesInFolder(virtualFoldERPath)方法获取指定文件夹里的文件,并将其绑定到ID为PicturesInFolder的DataList控件里.而SelectedNodeChanged事件处理器仅仅简单的调用DisplayPicturesInFolder(virtualFolderPath)方法,传入选定节点的value值.
Protected Sub PictureTree_SelectedNodeChanged(ByVal sender As Object, ByVal e As
System.EventArgs) Handles PictureTree.SelectedNodeChanged
'Refresh the DataList whenever a new node is selected
DisplayPicturesInFolder(PictureTree.SelectedValue)
End Sub
Private Sub DisplayPicturesInFolder(ByVal virtualFolderPath As String)
'Security check: make sure folderPath starts with VirtualImageRoot and doesn't include any
".."
If Not virtualFolderPath.StartsWith(VirtualImageRoot) OrElse virtualFolderPath.IndexOf("..")
>= 0 Then
Throw New ApplicationException("Attempting to view a folder outside of the public image
folder!")
End If
'Get information about the files in the specified folder
Dim folder As New DirectoryInfo(Server.MapPath(virtualFolderPath))
Dim fileList As FileInfo() = folder.GetFiles()
PicturesInFolder.DataSource = fileList
PicturesInFolder.DataBind()
End Sub
注意:
DisplayPicturesInFolder(virtualFoldERPath)方法里的第一行代码首先做了一个检查,确保被请求的路径位于常量VirtualImageRoot指定的根目录下.
ID为PicturesInFolder的DataList控件只包含了一个ItemTemplate模板,该模板显示了图片的名字(没有包含文件扩展名),并包含一个Image Web控件来展示该图片:
<ASP:DataList ID="PicturesInFolder" runat="server" Width="100%" CellPadding="5">
<ItemTemplate>
<h3><asp:Label runat="server" ID="FileNameLabel" Text='<%#
System.IO.Path.GetFilenameWithoutExtension(Eval("Name")) %>'></asp:Label></h3>
<asp:Image runat="server" ID="Picture" ImageUrl='<%# PictureTree.SelectedValue & Eval
("Name").ToString() %>' />
<br /><br />
</ItemTemplate>
<AlternatingItemStyle BackColor="#E0E0E0" />
</asp:DataList>
最终的效果是一个简单的图片管理程序。TreeView控件列出了文件系统里某个根目录下的子文件夹,点击某个具体的文件夹,其包含的图片将显示在右边.在web server里上载,编辑或删除image文件,该程序立马就能反映出这些改动!
图2
图3