TreeView服务器控件

TreeView服务器控件是ASP.NET 2.0引入的另一个新控件,笔者非常喜欢这个控件。TreeView服务器控件是一个功能非常丰富的控件,可以显示层次数据,很适合显示包含在.sitemap文件中的内容。图16-8说明了该控件如何显示本章前面一直在使用的站点地图(程序清单16-1)的内容。该图首先在屏幕顶部显示了一个完全折叠的TreeView控件,第二个TreeView控件是完全展开的。
图  16-8
这个控件可以通过它的折叠框架动态加载要显示的节点,即使这些节点是隐藏的,也可以加载。如果该控件使用客户端脚本显示树型视图的输出,当有人展开了该控件中的一个节点,以显示选中项的子节点时,该控件就可以向服务器回送一个调用。如果站点导航系统比较大,这是很理想的。此时,动态加载TreeView控件的节点可以大大提高性能。这个回送功能的优点是,它在底层实现,不需要完全刷新ASP.NET页面。当然,只有浏览器接受TreeView控件生成的客户端代码时,才能使用这个功能。如果浏览器不接受,该控件就只显示相应的内容(显示TreeView控件需要的所有信息)。它只为能处理服务器端脚本的客户执行这些基于JavaScript的回送。
在受某种HTTP嗅探器(用于监控网络上的通信)监控的页面上运行,肯定可以看到TreeView控件显示的内容。
提示:
推荐使用Microsoft的Eric Lawrence,可以从Internet的fiddlertool.com上免费下载它。
如果浏览器支持客户端脚本,展开TreeView控件的一个节点,HTTP请求就如下所示:
POST /Navigation/Default.aspx HTTP/1.1
Accept: */*
Accept-Language: en-us
Referrer: http://localhost:1882/Navigation/Default.aspx
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR
2.0.50727; InfoPath.1)
Host: localhost:1882
Content-Length: 904
Proxy-Connection: Keep-Alive
Pragma: no-cache
__EVENTTARGET=&__EVENTARGUMENT=&TreeView1_ExpandState=c&TreeView1_Selec
tedNode=TreeView1t0&TreeView1_PopulateLog=&__VIEWSTATE=%2FwEPDwUKLTY0OD
k0OTE2Mg9kFgICBA9kFBICAw88KwAJAgAPFggeDU5ldmVyRXhwYW5kZWRkHgtfIURhdGFCb
3VuZGceDFNlbGVKTm9kZQULVHJlZVZpZXcxdDAeCUxhc3RJbmRleAIBZAgUKwACDQMwOjAU
KwACFhAeBFRleHQFBEhvbWUehvbWUeBVZhbHVlBQRIb21lHgtOYXZpZ2F0ZVVybAUYL05hd
mlnYXRpb24vRGVmYXVsdC5hcB4HgdUb29sVGlwBQlIb21lIFBhZ2UeCERhdGFQYXRoBRgvb
mF2aWdhdGlvbi9kZWZhdWx0LmFzcHgeCURhdGFCb3VuZGceCFNlbGVjdGVkZx4QUG9wdWxh
dGVPbkRlbWFuZGdkZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WAwURTG9
naW4xJFJlbWVtYmVyTWUFF0xvZ2luMSRMb2dpbkltYWdlQnV0dG9uBQlUcmVlVmlldzFtws
zVpUMxFTDtpERnNjgEIkWWbg%3D%3S&login1$UserName=&login1$Password=&__CALL
BACKID=TreeView1&__CALLBACKIDPARAM=0%7C1%7Ctft%7Chome%7C%2Fnavigation%2
Fdefault.aspxHome&__EVENTVALIDATION=%2FwEWBgKg8Yn8DwKUvNa1DwL666vYDAKC0
q%2BkBgKnz4ybCAKn5fLxBaSy6WQwPagNZsHisWRoJfuiopOe
ASP.NET应用程序的响应不是包含TreeView控件的整个页面,而是一小段HTML,它由页面上的一个JavaScript方法使用,并动态加载到TreeView控件上。该响应如下所示:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/8.0.0.0
Date: Sat, 11 Feb 2006 17:55:02 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: private, no-store
Content-Type: text/html; charset=utf-8
Content-Length: 1756
Connection: Close
112|wEwCgKg8Yn8DwKUvNa1DwL666vYDAKC0Q+kBgKnz4ybCAKn5fLxBQKAgtPaBALEmcbh
CgK8nZDfCALM/ZK8AR/nFcl4nlPgp6HcF1U6YiFBfoNM14|nn|<div id="TreeViewln6Nodes"
Style="display:none;">
  <table cellpadding="0" cellspacing="0" style="border-width:0;">
    <tr>
        <td><div style="width:20px;height:1px"></div></td><td><div
style="width:20px;height:1px"><img
src="/Navigation/WebRourse.axd?d=GOWKLGnbFU9fYyyPCMT8DIfng
U4PxeMiAHxJNuXb-tU1&amp;t=632662834831594592" alt="" />
</div></td><td><img
src="/Navigation/WebRourse.axd?d=GOWKLGnbFU9fYyyPCMT8DIfng
U4PxeMiAHxJNuXb-tU1&amp;t=632662834831594592" alt="" />
</div></td><td><img
src="/Navigation/WebRourse.axd?d=GOWKLGnbFU9fYyyPCMT8DIfng
U4PCMT8DCXmyNCWX5x-n_pSXFIW2qE1&amp;t=632662834831594592"
alt="" />
</td><td style="white-space:nowrap;">
<a href="/Navigation/MarketsUSasdf.aspx"
 title="Looking at the U.S. Market" id="TreeView1t12"
style="text-decoration:none;">U.S. Market Report</a></td>
    </tr>
  </table><table cellpadding="0" cellspacing="0" style="border-width:0;">
    <tr>
        <td><div style="width:20px;height:1px"></div></td><td><div
style="width:20px;height:1px"><img
src="/Navigation/WebRourse.axd?d=GOWKLGnbFU9fYyyPCMT8DIfng
U4PxeMiAHxJNuXb-tU1&amp;t=632662834831594592" alt="" />
</div></td><td><div style="width:20px;height:1px"><img
src="/Navigation/WebRourse.axd?d=GOWKLGnbFU9fYyyPCMT8DIfng
U4PxeMiAHxJNuXb-tU1&amp;t=632662834831594592" alt="" />
</div></td><td><img
src="/Navigation/WebRourse.axd?d=GOWKLGnbFU9fYyyPCMT8DIfng
U4PCMT8DgyYai5iS-79vjeYzzdeJoiI1&amp;t=632662834831594592"
alt="" />
</td><td style="white-space:nowrap;">
<a href="/Navigation/NYSE.aspx"
 title="The New York Stock Exchange" id="TreeView1t13"
style="text-decoration:none;">NYSE</a></td>
    </tr>
</table>
</div>
这个回送功能相当强大,但如果要禁用它(甚至可以使用回送功能的浏览器也可以禁用它),只需把TreeView控件的PopulateNodesFromClient属性设置为false(默认值为true)。
TreeView控件的可定制性很高,但首先看看如何使用程序清单16-1中的.sitemap文件创建该控件的默认版本。这个例子继续使用前面创建的MarketsUS.aspx页面。
首先在页面上创建一个SiteMapDataSource控件。在使用TreeView控件显示.sitemap文件的内容时,必须使用一个数据源控件。TreeView控件不像SiteMapPath控件那样能自动绑定到站点地图文件上。
有了一个基本的SiteMapDataSource控件后,就把一个TreeView控件放在页面上,将DataSourceId属性设置为SiteMapDataSource1。完成后,代码如程序清单16-6所示。
程序清单16-6  基本的TreeView控件
<%@ Page Language="VB" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Using the TreeView Server Control</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:SiteMapPath ID="SiteMapPath1" runat="server">        
        </asp:SiteMapPath>
        <br /><p>
        <asp:TreeView ID="TreeView1" runat="server"
         DataSourceID="SiteMapDataSource1">
        </asp:TreeView>
        <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" /></p>
    </form>
</body>
</html>
运行页面,扩展TreeView控件,结果如图16-9所示。
图  16-9
这是一个非常基本的TreeView控件。这个控件的优点是允许进行高度定制,甚至可以使用ASP.NET 2.0中预定义的样式。
16.3.1  标识TreeView控件的内置样式
如前所述,TreeView控件有许多预置的样式。利用这些预定义样式的最佳方式是在页面的设计视图中进行。在Visual Studio 2005的设计视图中,右击页面上的TreeView控件,找到Auto Format选项。单击这个选项,就可以使用许多样式了。选择其中一个样式就会修改TreeView控件的代码,使之适应选中的样式。例如,从选项列表中选择MSDN,所创建的TreeView控件就转换为程序清单16-7中的样式。
程序清单16-7  应用MSDN样式的TreeView控件
<asp:TreeView ID="TreeView1" runat="server" DataSourceID="SiteMapDataSource1"
 ImageSet="Msdn" NodeIndent="10">
   <SelectedNodeStyle BackColor="White" VerticalPadding="1" Border Color="#888888"
    BorderStyle="Solid" BorderWidth="1px"
    HorizontalPadding="3"></SelectedNodeStyle>
   <NodeStyle VerticalPadding="2" Font-Names="Verdana" Font-Size="8pt"
    NodeSpacing="1" HorizontalPadding="5" ForeColor="Black"></NodeStyle>
   <HoverNodeStyle BackColor="#CCCCCC" BorderColor="#888888" Border Style="Solid"
    BorderWidth="1px" Font-Underline="True"></HoverNodeStyle>
</asp:TreeView>
使用这些内置样式,完全改变TreeView控件的外观和操作方式并不难。运行这段代码,结果如图16-10所示。
图  16-10
16.3.2  TreeView控件的各个部分
为了掌握TreeView控件的使用,必须理解该控件创建的层次结构树的每个部分所使用的术语。
首先,TreeView控件上的每个元素或每一项都称为节点。层次结构中最上面的节点是根节点。TreeView控件可以有多个根节点。在层次结构中,任何节点,包括根节点在内,如果在它的下面还有节点,就称为父节点。每个父节点可以有一个或多个子节点。如果节点不包含子节点,就称为叶节点。
下面根据前面的站点地图详细说明了这些术语的用法:
Home – 根节点, 父节点
   News – 父节点, 子节点
      U.S. – 子节点, 叶节点
      World – 子节点, 叶节点
      Technology – 子节点, 叶节点
      Sports – 子节点, 叶节点
   Finance – 父节点, 子节点
      Quotes - 子节点, 叶节点
      Markets – 父节点, 子节点
         U.S. Market Report – 子节点, 叶节点
         NYSE – 子节点, 叶节点
      Funds – 子节点, 叶节点
   Weather – 子节点, 叶节点
在这个程序清单中,可以看出每个节点是什么,它在节点层次结构中如何表示。例如,U.S. Market Report节点是一个叶节点,表示它没有与之相关的子节点。但是,它还是Markets节点的一个子节点,Markets节点又是U.S. Market Report节点的父节点。如果直接处理Markets节点,它还是Finance节点的一个子节点,Finance节点是它的父节点。其要点是站点地图中的每个节点都与层次结构中的其他节点相关。必须理解这些关系,才能编程处理这些节点(如本章后面所述),用于处理它们的方法包括RootNode、CurrentNode和ParentNode。
16.3.3  在XML文件中绑定TreeView控件
要填充TreeView控件的节点,不仅可以使用.sitemap文件,还有许多其他方式。一种比较好的方式是使用XmlDataSource控件(而不是SiteMapDataSource控件)从XML文件中填充TreeView控件。
例如,在XML文件Hardware.xml中创建项目的层次列表,如程序清单16-8所示。
程序清单16-8  Hardware.xml
<?xml version="1.0" encoding="utf-8"?>
<Hardware>
    <Item Category="Motherboards">
        <Option Choice="Asus" />
        <Option Choice="Abit" />
    </Item>
    <Item Category="Memory">
        <Option Choice="128mb" />
        <Option Choice="256mb" />
        <Option Choice="512mb" />
    </Item>
    <Item Category="HardDrives">
        <Option Choice="40GB" />
        <Option Choice="80GB" />
        <Option Choice="100GB" />
    </Item>
    <Item Category="Drives">
        <Option Choice="CD" />
        <Option Choice="DVD" />
        <Option Choice="DVD Burner" />
    </Item>
</Hardware>
可以看出,这个列表不能用于站点导航,但允许终端用户从选项的层次列表中选择。这个XML文件分为4个选项类型:Motherboards、Memory、HardDrives和Drives。要把TreeView控件绑定到这个XML文件上,可以使用XmlDataSource控件指定所用XML文件的位置。然后在TreeView控件中使用<asp:TreeNodeBinding>元素指定要绑定XML文件中的哪些元素,来填充TreeView控件的节点。如程序清单16-9所示。
程序清单16-9  把TreeView控件绑定到Hardware.xml文件上
<%@ Page Language="VB" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Latest Hardware</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:TreeView ID="Treeview1" runat="server" DataSourceID="Xmldatasource1">
            <DataBindings>
                <asp:TreeNodeBinding DataMember="Hardware"
                 Text="Computer Hardware" />
                <asp:TreeNodeBinding DataMember="Item" TextField="Category" />
                <asp:TreeNodeBinding DataMember="Option" TextField="Choice" />
            </DataBindings>
        </asp:TreeView>
        <asp:XmlDataSource ID="Xmldatasource1" runat="server"
         DataFile="Hardware.xml">
        </asp:XmlDataSource>
    </form>
</body>
</html>
要介绍的第一项是<asp:XmlDataSource>控件,它与前面的<asp:SiteMapDataSource>控件一样简单,但使用DataFile属性指向Hardware.xml文件。
下一步是创建一个TreeView控件,绑定到这个XML文件上。可以把默认的TreeView控件直接绑定到XmlDataSource控件上,如下所示:
<asp:TreeView ID="TreeView1" runat="server" DataSourceId="XmlDataSource1" />
完成后,不正确的结果如图16-11所示。
图  16-11
可以看出,TreeView控件已绑定到Hardware.xml文件上,但查看TreeView控件中的节点就会发现,它只显示了文件中XML元素的名称。这不是我们想要的,所以应在TreeView控件中使用<DataBindings>元素指定如何绑定到XML文件上。
<DataBindings>元素封装了一个或多个TreeNodeBinding对象。TreeNodeBinding对象的两个比较重要的属性是DataMember和TextField。DataMember属性指向TreeView控件要查找的XML元素的名称,TextField属性指定TreeView在该XML元素中查找的XML属性。如果操作正确,使用<DataBindings>元素会得到如图16-12所示的结果。
图  16-12
在程序清单16-9中,可以重写XML文件中根节点的文本值<Hardware>,在TreeView控件中把它显示为Computer Hardware:
<asp:TreeNodeBinding DataMember="Hardware" Text="Computer Hardware" />
16.3.4  在TreeView中选择多个选项
如前所述,TreeView控件主要不用于导航,但可以用于其他用途。在许多情况下,TreeView控件可以显示一个层次结构列表,让终端用户从中选择一项或多项。
TreeView控件的一个重要的内置功能是在列表中,把复选框放在层次结构项中的节点旁边。这些复选框可以让终端用户进行多项选择。TreeView控件有一个ShowCheckBoxes属性,可用于在项目列表中给许多不同类型的节点创建复选框。
属性ShowCheckBoxes的值如表16-3所示。
  表  16-3
说    明
All
给TreeView控件中的每个节点应用复选框
Leaf
给没有子元素的节点应用复选框
None
不给TreeView控件中的节点应用复选框
Parent
给TreeView控件中的父节点应用复选框。父节点至少有一个与之相关的子节点
Root
给TreeView控件中的每个根节点应用复选框
在使用ShowCheckBoxes属性时,可以在控件中明确设置它:
<asp:TreeView ID="Treeview1" runat="server" Font-Underline="false"
 DataSourceID="Xmldatasource1" ShowCheckBoxes="Leaf">
   ...
</asp:TreeViewTreeView>
或者使用下面的代码编程设置它:
VB
TreeView1.ShowCheckBoxes = TreeNodeTypes.Leaf
C#
TreeView1.ShowCheckBoxes = TreeNodeTypes.Leaf;
为了演示使用复选框和TreeView控件,下面继续扩展程序清单16-9中的计算机硬件示例。创建一个层次结构列表,让人们从列表中选择多个选项,以接收更多的信息,如程序清单16-10所示。
程序清单16-10  在节点的层次结构列表中给叶节点应用复选框
VB
<%@ Page Language="VB" %>
<script runat="server">   
   Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        If TreeView1.CheckedNodes.Count > 0 Then
            Label1.Text = "We are sending you information on:<p>"
               
            For Each node As TreeNode In TreeView1.CheckedNodes
                Label1.Text += node.Text & " " & node.Parent.Text & "<br>"
            Next
        Else
            Label1.Text = "You didn't select anything. Sorry!"
        End If
   End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Latest Hardware</title>
</head>
<body>
    <form runat="server">
    Please select the items you are interested in:
        <p>
        <asp:TreeView ID="TreeView1" runat="server" Font-Underline="False"
         DataSourceID="XmlDataSource1" ShowCheckBoxes="Leaf">
            <DataBindings>
                <asp:TreeNodeBinding DataMember="Hardware"
                 Text="Computer Hardware" />
                <asp:TreeNodeBinding DataMember="Item" TextField="Category" />
                <asp:TreeNodeBinding DataMember="Option" TextField="Choice" />
            </DataBindings>
        </asp:TreeView>
        <p>
        <asp:Button ID="Button1" runat="server" Text="Submit Choices"
         OnClick="Button1_Click" />
        </p>
        <asp:XmlDataSource ID="XmlDataSource1" runat="server"    
         DataFile="Hardware.xml">
        </asp:XmlDataSource>
       </p>
       <asp:Label ID="Label1" runat="Server" />
    </form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<script runat="server">   
    protected void Button1_Click(object sender, System.EventArgs e)
    {
        if (TreeView1.CheckedNodes.Count > 0)
        {
            Label1.Text = "We are sending you information on:<p>";
            foreach (TreeNode node in TreeView1.CheckedNodes)
            {
                Label1.Text += node.Text + " " + node.Parent.Text + "<br>";
            }
        }
        else
        {
            Label1.Text = "You didn't select anything. Sorry!";
        }
    }   
</script>
在这个例子中,首先把ShowTextBoxes属性设置为Leaf,表示在TreeView控件中仅为不包含任何子节点的项添加复选框。带复选框的项应是层次结构列表扩展后的最后一项。
设置了这个属性后,就要在Button1_Click事件中处理终端用户选择的项。首先要检查是否选择了选项:
If TreeView1.CheckedNodes.Count > 0 Then
   ...
End If
在这个例子中,回送时选中节点的数量必须大于0,表示至少选择了一项。如果是这样,就可以执行If语句中的代码。然后If语句会填充页面上的Label控件。要使用选中节点的数据填充Label控件,需要使用一个For Each语句,如下所示:
For Each node As TreeNode In TreeView1.CheckedNodes
   ...
Next
这会创建一个TreeNode对象实例,在选中节点的TreeView1集合中检查每个TreeNode对象。
对于每个选中的节点,需要获取节点的Text值,以及其父节点的Text值,以进一步填充Label控件:
Label1.Text += node.Text & " " & node.Parent.Text & "<br>"
最后,页面生成的结果如图16-13所示。
图  16-13
16.3.5  在TreeView控件中指定定制的图标
可以对TreeView控件进行高度的定制。本章前面提到,指定一个内置样式,很容易定制TreeView控件的外观和操作方式。应用其中一个样式,会显著改变该控件的外观。一个最引人瞩目的改变是TreeView控件中用于节点的图标。还可以把自己的图标应用于节点层次结构列表中的节点,但这不如选择TreeView控件中内置的样式那么简单。
TreeView控件包含如表16-4所示的属性。这些属性可以为控件的节点指定自己的图像。
表  16-4
属    性
说    明
CollapseImageUrl
如果展开后节点显示出有子节点,且可以折叠,就给该节点应用定制的图像
ExpandImageUrl
如果节点可以展开,显示其子节点,就给该节点应用定制的图像
LeafImageUrl
如果节点没有子节点,且位于节点层次结构链的最后,就给该节点应用定制的图像
NoExpandImageUrl
如果编程时节点不能展开,或者它本身是叶节点,就给该节点应用定制的图像。它主要用于加上空格,使叶节点与其父节点对齐
ParentNodeImageUrl
仅对TreeView控件中的父节点应用定制的图像
RootNodeImageUrl
仅对TreeView控件中的根节点应用定制的图像
程序清单16-11是这些属性的用法示例。
程序清单16-11  给TreeView控件应用定制的图像
<asp:TreeViewTreeView ID="TreeView1" runat="server" Font-Underline="False"
 DataSourceId="XmlDataSource1"
 CollapseImageUrl="Images/CollapseImage.gif"
 ExpandImageUrl="Images/ExpandImage.gif"
 LeafImageUrl="Images/LeafImage.gif">
   <DataBindings>
      <asp:TreeNodeBinding DataMember="Hardware" Text="Computer Hardware" />
      <asp:TreeNodeBinding DataMember="Item" TextField="Category" />
      <asp:TreeNodeBinding DataMember="Option" TextField="Choice" />
   </DataBindings>
</asp:TreeView>
在控件的节点前面指定这3个图像,会重写使用加号(+)和减号(-)来展开和折叠节点的默认值。当默认什么也不使用时,还可以为任意叶节点使用一个图像来覆盖默认值。运行程序清单16-11的代码,结果如图16-14所示(当然取决于读者使用的图像)。
图  16-14
16.3.6  指定用于连接节点的线条
TreeView控件把项的层次结构列表显示给终端用户,有时我们想把这些层次结构项之间的关系显示得更清晰一些。一种方式是在父节点和子节点之间显示连接线。把TreeView控件的ShowLines属性设置为True即可(该属性默认设置为False)。
<asp:TreeViewTreeView ID="TreeView1" runat="server" Font-Underline="False"
 DataSourceId="XmlDataSource1" ShowCheckBoxes="Leaf" ShowLines="True">
   ...
</asp:TreeViewTreeView>
执行这段代码得到的结果如图16-15所示。
图  16-15
如果ShowLines属性设置为True,还可以在TreeView控件中定义自己的线条和图像。这是很容易的,因为Visual Studio 2005提供了ASP.NET TreeView Line Image Generator工具。这个工具可以可视化地设计线条的外观以及相关的展开和折叠图像。建立好自己的线条和图像后,该工具就会创建所有必需的文件,供TreeView控件使用。
要获得这个工具,可以进入文件的设计视图,单击页面上TreeView控件的智能标记。找到Customize Line Images选项。单击它,就会打开ASP.NET TreeView Line Generator对话框,如图16-16所示。
图  16-16
在这个对话框中,可以为需要Expand、Collapse或NoCollapse图标的节点选择图像。还可以指定连接节点的线条的颜色和样式。在创建自己的样式时,对话框中会根据所使用的样式显示TreeView控件的示例输出。最后一步是选择这个对话框创建的文件输出。完成这一步后,单击OK按钮,在对话框指定的文件夹中就会生成一个很长的新文件列表。默认情况下,ASP.NET TreeView Line Image Generator把输出文件夹命名为TreeLineImages,但用户可以把它命名为任意名称。如果项目中不存在这个文件夹,Visual Studio就会创建这个文件夹。之后,TreeView控件就可以通过设置LineImagesFolderUrl属性,来使用新的图像和样式了,如下所示:
<asp:TreeViewTreeView ID="TreeView1" runat="server" ShowLines="True"
 DataSourceId="SiteMapDataSource1" LineImagesFolderUrl="TreeViewLineImages">
重要的属性显示为黑体。ShowLines属性必须设置为True。之后,使用前面显示的默认设置,除非指定一个位置,使用LineImagesFolderUrl属性从中提取定制的图像和样式。可以看出,这里该属性指向新文件夹TreeViewLineImages,其中包含了我们创建的所有新图像和样式。查看该文件夹,了解一下该工具都生成了哪些输出。
16.3.7  编程使用TreeView控件
前面学习了如何声明性地使用TreeView控件。ASP.NET的一个优点是不仅可以声明性地使用它的组件,还可以编程操作这些控件。
TreeView控件有一个相关的TreeView类,可以在代码中完整地管理TreeView控件及其操作方式。下一节将介绍如何使用较常见的方式编程控制TreeView。
1. 编程扩展和折叠节点
使用TreeView控件可以在层次结构中编程扩展或折叠节点。为此,要使用TreeView类中的ExpandAll或CollapseAll方法。程序清单16-12显示了前面在程序清单16-6中的一个TreeView控件,并在它的上面添加了两个按钮,用于启动节点的扩展和折叠。
程序清单16-12  编程扩展或折叠TreeView控件的节点
VB
<%@ Page Language="VB" %>
<script runat="server" language="vb">   
   Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        TreeView1.ExpandAll()
   End Sub
   
   Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        TreeView1.CollapseAll()
   End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>TreeView Control</title>
</head>
<body>
    <form id="Form1" runat="server">
        <p>
            <asp:Button ID="Button1" runat="server" Text="Expand Nodes"
             OnClick="Button1_Click" />
            <asp:Button ID="Button2" runat="server" Text="Collapse Nodes"
             OnClick="Button2Click" />
            <br />
            <br />
        <asp:TreeView ID="TreeView1" runat="server"
         DataSourceId="SiteMapDataSource1">
        </asp:TreeView>
        <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" /></p>
    </form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<script runat="server">   
    protected void Button1_Click(object sender, System.EventArgs e)
    {
        TreeView1.ExpandAll();
    }
   
    protected void Button2_Click(object sender, System.EventArgs e)
    {
        TreeView1.CollapseAll();
    }
</script>
运行这个页面,会在TreeView控件的上面显示两个按钮。单击第一个按钮,调用ExpandAll方法,展开整个节点列表。单击第二个按钮,调用CollapseAll方法,把所有的节点折叠起来,如图16-17所示。
图  16-17
程序清单16-12中的例子非常好,但它只根据终端用户的操作(终端用户单击按钮)来展开和折叠节点。如果可以编程启动这些操作就更好了。
用户可能想把TreeView1.ExpandAll()命令放在Page_Load事件中,但如果这么做,代码就不工作了,应使用TreeView控件中的OnDataBound属性:
<asp:TreeView ID="TreeView1" runat="server"
 DataSourceId="SiteMapDataSource1" OnDataBound="TreeView1_DataBound">
</asp:TreeView>
这个属性的值指向代码中的一个方法,如下所示:
VB
Protected Sub TreeView1_DataBound(ByVal sender As Object, _
  ByVal e As System.EventArgs)
   TreeView1.ExpandAll()
End Sub
C#
protected void TreeView1_DataBound(object sender, System.EventArgs e)
{
   TreeView1.ExpandAll();
}
现在运行页面,注意在浏览器上第一次加载页面时,TreeView控件会完全展开。
还可以展开树中特定的节点,而不是展开整个列表。为此,使用刚才创建的TreeView1_ DataBound方法。使用程序清单16-1中的站点地图,修改TreeView1_DataBound方法,如程序清单16-13所示。
程序清单16-13  编程展开特定的节点
VB
Protected Sub TreeView1_DataBound(ByVal sender As Object, _
  ByVal e As System.EventArgs)
   TreeView1.CollapseAll()
   TreeView1.FindNode("Home").Expand()
   TreeView1.FindNode("Home/Finance").Expand()
   TreeView1.FindNode("Home/Finance/Markets").Expand()
End Sub
C#
protected void TreeView1_DataBound(object sender, System.EventArgs e)
{
   TreeView1.CollapseAll();
   TreeView1.FindNode("Home").Expand();
   TreeView1.FindNode("Home/Finance").Expand();
   TreeView1.FindNode("Home/Finance/Markets").Expand();
}
在这个例子中,使用了FindNode方法展开所找到的节点。FindNode方法带有一个字符串参数,其值是要引用的节点和节点路径。例如TreeView1.FindNode(“Home/Finance”)
.Expand()展开Finance节点。要找到节点,必须指定从根节点到要处理的节点(这里是Finance节点)的完整路径。在站点地图路径结构中,站点地图路径的各个节点之间用一个斜杠来分隔开。
注意,必须依次展开每个节点,直到到达Finance节点为止。如果在TreeView1_Data Bound方法中只使用TreeView1.FindNode(“Home/Finance/Markets”).Expand(),Finance节点会展开,但它上面的父节点Finance和Home不会展开,在调用页面时看不到展开的Markets节点。
如果不使用Expand方法,还可以把Expanded属性设置为True,如程序清单16-14所示。
程序清单16-14  使用Expanded属性编程展开节点
VB
Protected Sub TreeView1_DataBound(ByVal sender As Object, _
  ByVal e As System.EventArgs)
   TreeView1.CollapseAll()
   TreeView1.FindNode("Home").Expanded = True
   TreeView1.FindNode("Home/Finance").Expanded = True
   TreeView1.FindNode("Home/Finance/Markets").Expanded = True
End Sub
C#
protected void TreeView1_DataBound(object sender, System.EventArgs e)
{
   TreeView1.CollapseAll();
   TreeView1.FindNode("Home").Expanded = true;
   TreeView1.FindNode("Home/Finance").Expanded = true;
   TreeView1.FindNode("Home/Finance/Markets").Expanded = true;
}
这里主要讨论的是Expand方法和Expanded属性,还可以使用Collapse方法编程折叠节点。但实际上不存在Collapsed属性,而可以把Expanded属性设置为False。
2. 添加节点
使用TreeView控件可以完成的另一个有趣任务是给整个层次结构编程添加节点。TreeView控件由TreeNode对象的集合组成。如前面的例子所示,Finance节点实际上是一个可以编程处理的TreeNode对象。该对象可以添加其他TreeNode对象。
通常情况下,TreeNode对象存储Text和Value属性。Text属性是TreeView控件中显示给终端用户的内容。Value属性是一个附加的数据项,可用于关联这个TreeNode对象。另一个可以使用的属性(假定控件是一个导航链接列表)是NavigateUrl。程序清单16-15演示了如何在程序清单16-1的站点地图中编程添加节点。
程序清单16-15  给TreeView控件编程添加节点
VB
<%@ Page Language="VB" %>
<script runat="server" language="vb">   
   Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        TreeView1.ExpandAll()
   End Sub
   
   Protected Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        TreeView1.CollapseAll()
   End Sub
   
   Protected Sub Button3 _Click(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim myNode As New TreeNode
        myNode.Text = TextBox1.Text
        myNode.NavigateUrl = TextBox2.Text
        TreeView1.FindNode("Home/Finance/Markets").ChildNodes.Add(myNode)
   End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>TreeView Control</title>
</head>
<body>
    <form id="Form1" runat="server">
        <p>
            <asp:Button ID="Button1" runat="server" Text="Expand Nodes"
             OnClick="Button1_Click" />
            <asp:Button ID="Button2" runat="server" Text="Collapse Nodes"
             OnClick="Button2_Click" /></p>
        <p>
            <strong>Text of new node:</strong>
            <asp:TextBox ID="TextBox1" runat="server">
            </asp:TextBox>
        </p>
        <p>
            <strong>Desination URL of new node:</strong>
            <asp:TextBox ID="TextBox2" runat="server">
            </asp:TextBox>
            <br />
            <br />
            <asp:Button ID="Button3" runat="server" Text="Add New Node"
             OnClick="Button3_Click" />
        </p>
        <p>
        <asp:TreeView ID="TreeView1" runat="server"
         DataSourceId="SiteMapDataSource1">
        </asp:TreeView></p>
        <p>
        <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" /></p>
    </form>
</body>
</html>
C#
protected void Button3_Click(object sender, System.EventArgs e)
{
   TreeNode myNode = new TreeNode();
   myNode.Text = TextBox1.Text;
   myNode.NavigateUrl = TextBox2.Text;
   TreeView1.FindNode("Home/Finance/Markets").ChildNodes.Add(myNode);
}
这个页面包含两个文本框和一个新的按钮控件。第一个文本框用于填充所创建的新节点的Text属性,第二个文本框用于填充新节点的NavigateUrl属性。
如果运行页面,则单击Expand Nodes按钮就可以展开整个层次结构。接着给Markets节点添加子节点。要编程添加新节点,应与前面一样使用FindNode方法查找Markets节点。找到它后,就可以使用ChildNodes.Add方法,传送一个TreeNode对象实例,来添加子节点。提交第一个文本框中的NASDAQ和第二个文本框中的Nasdaq.aspx,会使TreeView控件变为如图16-18所示的模样。
图  16-18
添加了节点后,即使把层次结构折叠起来,再展开,该节点也已添加进去。可以给Markets节点添加任意多个子节点。注意,可以编程修改节点,但不能改变数据源的内容(XML文件或.sitemap文件)。这些数据源在整个过程中保持不变。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值