C#开发训练营

第2课:ASP.NET(2)——常用Web控件

使用Web窗体构建页面时,可以使用一系列的Web控件,它们定义在System.Web.UI.WebControls命名空间中,可以在帮助文档中查询详细的定义。本课将讨论一些常用的控件,包括基本的应用和一些实用技巧,以及如何结合客户端元素进行灵活的操作。

Web控件会一些基本的属性,如ID属性设置控件在页面中的唯一标识,runat属性设置为server表示这是在服务器端进行处理的控件。当控件中有不能识别的属性时,会原样发送到客户端处理,通过这一特性,可以很方便地在Web控件中添加客户端处理属性,比如,在文本框中可以添加HTML5标准中新增的required属性,以提醒用户输入内容,也可以直接使用style属性设置元素的样式等。

按钮类控件

Web窗体中,常用的按钮类型包括Button、LinkButton、ImageButton。使用这些按钮控件时,OnClick事件用于定义服务器端的单击响应代码,如果需要设置客户端的单击响应,则需要使用OnClientClick事件,并定义相应的JavaScript代码。比如,一个简单的操作提示就可以通过OnClientClick事件来实现,如下面的代码。

ASP.NET
<asp:Button ID="btnTest" Text="测试" runat="server" 
        OnClientClick="return confirm('真的要提交测试操作吗');" />

当点击此按钮时,会在客户端显示确认对话框,如图1,用户确认后才将窗体数据提交到服务器端,用户选择取消时不提交窗体数据。

图1

Button控件在客户端呈现为type属性为submit的input元素;LinkButton控件显示为a元素;ImageButton控件可以通过ImageUrl属性设置按钮显示图片的路径,在客户端显示为type属性为image的input元素。

文本类控件

ASP.NET窗体中,文本类的控件主要包括Literal、Label和TextBox,其中:

  • Literal控件,通过Text属性设置页面中显示的内容。
  • Label控件中,Text属性设置的内容会显示在一个span元素中。
  • TextBox控件,可以使用TextMode属性设置文本模式,单行(Single,默认类型)或密码(Password)模式时,控件显示为input元素,type属性分别是text和password。多行模式(MultiLine)时,控件显示为textarea元素。

TextBox控件应用时,对于普通文本框,即type属性等于text的input元素,可以直接设置一些客户端的事件,如键盘松开时的事件onkeyup,可以在客户端输入内容的同时进行一些同步操作。

HTML5标准中可以使用maxlength属性设置textarea元素的最大字符数,但TextBox控件的TextMode属性设置为MultiLine值时,MaxLength属性是无效的。为了解决textarea元素的maxlength属性问题,可以在客户端使用JavaScript代码进行操作,如下面的代码。

JavaScript
<script>
    window.onload = new function () {
        document.getElementById("txt1").setAttribute("maxlength", "200");
    };
</script>

代码中,假设txt1元素是TextBox控件的id,并且将TextMode属性设置为MultiLine值,控件会在客户端生成textarea元素;此时,可以通过HTML元素的setAttribute()方法设置属性值,这里将maxlength属性设置为200,即最多可以输入200个字符。请注意,textarea元素中计算字符数量时会包含回车、换行等不可见字符。

如果页面在客户端需要调用多个初始化函数,可以使用/lib/js/common.js文件中封装的addWinLoadFunc()函数,定义如下。

JavaScript
function addWinLoadFunc(fn) {
    if (typeof window.onload === "function") {
        var oldFn = window.onload;
        window.onload = function () {
            oldFn();
            fn();
        };
    } else {
        window.onload = fn;
    }
}

在页面中可以使用如下代码添加初始化函数。

JavaScript
<script src="/lib/js/common.js"></script>
<script>
    addWinLoadFunc(new function () {
        document.getElementById("txt1").setAttribute("maxlength", "200");
    });
</script>

列表类控件

列表类控件都有着相同的基类,即ListControl类,而Web窗体中使用的具体类型的列表控件包括:

  • ListBox,普通列表。
  • DropDownList,下拉列表。
  • RadioButtonList,单选按钮列表。
  • CheckBoxList,复选框列表。
  • BulletedList,显示普通列表,客户端呈现为ul元素。

列表中的项目定义为ListItem对象,其中,Text属性设置显示的文本内容,Value属性设置列表项的数据。此外,在ListBox、DropDownList和RadioButtonList控件中,选中项的Selected属性值为true。

下面的代码定义了选择称呼的选项。

ASP.NET
<asp:RadioButtonList ID="drpSex" RepeatDirection="Horizontal" runat="server">
    <asp:ListItem Value="0" Text="保密" Selected="True"></asp:ListItem>
    <asp:ListItem Value="1" Text="先生"></asp:ListItem>
    <asp:ListItem Value="2" Text="女士"></asp:ListItem>
</asp:RadioButtonList>

默认的显示效果如图2。

图2

对于ListBox、DropDownList和RadioButtonList控件,还有几个属性需要注意,如:

  • Items属性,表示列表项的集合,可以通过其中的Count属性获取列表项的数量,使用整数索引获取列表项,如第一个列表项可以通过Items[0]获取。
  • SelectedIndex属性,已选中列表项的索引,如果列表中没有项目,或者没有选择项目,属性值为-1。选中项目时,第一项索引值为0、第二项目索引值为1、以此类推。
  • SelectedItem属性,表示已选中的列表项对象,可以使用其中的Text属性获取列表项文本,Value属性获取列表项数据。
  • SelectedValue属性,直接获取已选中列表项的值(Value属性)。需要注意的是,在使用此属性前,应使用SelectedIndex属性判断是否已有选中的列表项。

CheckBoxList控件用于多选项目,获取选中的项目或项目数据时,应遍历所有的列表项,并通过列表项的Selected属性判断是否选中。下面的代码创建了一个包含多个选项的CheckBoxList控件。

HTML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="Test.aspx.cs" Inherits="Test" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <link rel="stylesheet" href="/lib/css/common.css" />
</head>
<body>
    <form id="form1" runat="server">
        <asp:CheckBoxList ID="drpChannel" runat="server" 
            RepeatDirection="Horizontal">
            <asp:ListItem Value="1" Text="汽车"></asp:ListItem>
            <asp:ListItem Value="2" Text="财经"></asp:ListItem>
            <asp:ListItem Value="3" Text="科技"></asp:ListItem>
            <asp:ListItem Value="4" Text="娱乐"></asp:ListItem>
            <asp:ListItem Value="5" Text="体育"></asp:ListItem>
        </asp:CheckBoxList>
        <asp:Button ID="btnTest" Text="测试" 
            runat="server" OnClick="btnTest_Click1" />
    </form>
</body>
</html>

页面显示效果如图3。

图3

下面的代码,在测试按钮中读取选中的复选列表项。

C#
using System;
using System.Collections.Generic;

public partial class Test : System.Web.UI.Page
{
    protected void btnTest_Click1(object sender, EventArgs e)
    {
        List<string> selValue = new List<string>();
        for(int i = 0; i < drpChannel.Items.Count; i++)
        {
            if (drpChannel.Items[i].Selected == true)
                selValue.Add(drpChannel.Items[i].Value);
        }
        //
        for (int i = 0; i < selValue.Count; i++)
            tWeb.WriteLine(selValue[i]);
    }
}

图4中显示了选中前三个选项并点击“测试”按钮的效果。

图4

如果只需要显示简单的列表,可以使用BulletedList控件,它会在页面中显示一个ul元素。如下面的代码可以生成一个简单的列表导航。

ASP.NET
<asp:BulletedList ID="lst1" runat="server" 
        DisplayMode="HyperLink" Target="_blank">
    <asp:ListItem Value="/" Text="主页"></asp:ListItem>
    <asp:ListItem Value="/Test.aspx" Text="ASPX测试页"></asp:ListItem>
    <asp:ListItem Value="/Test.html" Text="HTML测试页"></asp:ListItem>
</asp:BulletedList>

代码中,BulletedList控件中使用了DisplayMode属性,可选值包括:

  • Text,默认值,列表项显示为文本。
  • HyperLink,列表项显示为超链接,同时,可以使用Target属性指定链接打开的目标,其中,_blank是在新的窗口或新的标签中打开,_self是在当前窗口或标签中打开。此时ListItem组件的Value属性设置链接(a元素)的href属性值,Text属性设置a元素中显示的文本内容。
  • LinkButton,列表项显示链接按钮,可以使用Click事件响应列表项的点击操作,响应方法定义为(object sender, BulletedListEventArgs e),其中,e.Index属性可以获取点击项的索引值,使用lst1.Items[e.Index].Text可以获取点击项的文本(Text属性),使用lst1.Items[e.Index].Value可以获取点击项的值(Value属性)。

应用开发时,还可以很方便地将外部数据绑定到列表控件中,此时需要注意以下一些属性和方法:

  • DataSource属性,设置数据源,如DataTable等类型的对象。
  • DataValueField属性,设置列表项数据的字段名,对应ListItem对象的Value属性。
  • DataTextField属性,设置列表项显示文本的字段名,对应ListItem对象的Text属性。
  • DataBind()方法,执行绑定操作。

下面的代码会将源代码中/app_data/excel/t001_dict.xlsx文件中的数据绑定到名为lst1的ListBox控件中。

C#
DataTable tbl = tExcel.ReadExcel(
    tWeb.MapPath("/app_data/excel/t001_dict.xlsx"));
lst1.DataSource = tbl;
lst1.DataValueField = "fname";
lst1.DataTextField = "fdesc";
lst1.DataBind();

图5中显示了t001_dict.xlsx文件的内容,读取文件内容时,fname和fdesc会作为DataTable对象中的列名,然后将fname列的数据作为列表项的值(Value属性),fdesc列的数据作为列表项的文本(Text属性)。

图5

后续课程会讨论更多关于数据操作及Excel读写相关内容。

单选按钮和复选框

复选框(CheckBox)一般用于两种状态数据的操作,如“是/否”;应用时,可以使用Checked属性设置和获取选中状态。

单选按钮(RadioButton)定义为CheckBox类的子类,实际开发中,单选按钮并不经常单个使用,更多的是通过RadioButtonList控件选择多个元素中的一个。

日历

日历控件定义为Calendar类,可以在帮助文档中查看完整的下定义。下面的代码演示了一个基本的日历控件。

ASP.NET
<asp:Calendar ID="cale1" runat="server" 
    OnSelectionChanged="cale1_SelectionChanged" 
    TodayDayStyle-BackColor="LightYellow"></asp:Calendar>

其中,OnSelectionChanged设置了点击某一天的响应事件方法,TodayDayStyle-BackColor属性设置了当日的背景颜色,这里设置为浅黄色。日历显示效果如图6。

图6

在数据采集窗体中,这么大的控件可能并不美观,下面的示例,我们使用一个文本框显示选择的日期,而日历控件只在需要选择日期时显示。首先看HTML部分,如下面的代码(/demo/calendar/CalendarDemo.aspx)。

HTML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="CalendarDemo.aspx.cs" 
    Inherits="demo_calendar_CalendarDemo" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>日历控件演示</title>
    <link rel="stylesheet" href="/lib/css/common.css" />
</head>
<body>
    <form id="form1" runat="server">
        <div class="form_normal">
            <p>
                <label>请选择日期</label>
                <asp:TextBox ID="txtSelDate" ReadOnly="true" 
                    runat="server" Width="200" ></asp:TextBox>
                <a href="javascript:calendarSwitch();">选择</a>
                    <asp:Calendar ID="cale1" runat="server"
                        OnSelectionChanged="cale1_SelectionChanged"
                        TodayDayStyle-BackColor="LightYellow"
                        style="display:none;clear:both;width:260px;" >
                    </asp:Calendar>
            </p>
        </div>
    </form>
</body>
</html>
<script>
    function calendarSwitch() {
        var cale = document.getElementById("cale1");
        if (cale.style.display == "none") {
            // 显示
            cale.style.display = "block";
        } else {
            // 隐藏
            cale.style.display = "none";
        }
    }
</script>

页面中结合了HTML、CSS和JavaScript代码的综合应用,这也是Web应用开发灵活性的体现。图7中显示了页面中点击“选择”的效果。

图7

当选择一个日期后,会在txtSelDate文本框中以短日期格式显示,如图8所示。

图8

选择日期的响应代码定义在CalendarDemo.aspx.cs文件,内容如下。

C#
using System;

public partial class demo_calendar_CalendarDemo : System.Web.UI.Page
{
    // 其它代码…
    // 选择日期响应
    protected void cale1_SelectionChanged(object sender, EventArgs e)
    {
        txtSelDate.Text = cale1.SelectedDate.ToShortDateString();
    }
}

如果需要指定的格式显示日期,可以对SelectedDate属性获取的日期值进行相应的格式化。

菜单

页面中,菜单有很多实现方法,在ASP.NET中也进行相应的封装,如使用Menu控件定义菜单,并使用MenuItem类操作菜单项。

在/demo/menu/MenuDemo.aspx页面中演示了菜单的相关操作,首先看HTML部分,如下面的代码。

HTML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="MenuDemo.aspx.cs" Inherits="demo_menu_MenuDemo" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Menu ID="menu1" runat="server" 
            OnMenuItemClick="menu1_MenuItemClick">
            <Items>
                <asp:MenuItem Value="opt_1_1" Text="菜单一">
                </asp:MenuItem>
                <asp:MenuItem Value="opt_1_2" Text="菜单二">
                </asp:MenuItem>
                <asp:MenuItem Value="opt_1_3" Text="菜单三">
                    <asp:MenuItem Value="opt_1_3_1" Text="菜单三A">
                    </asp:MenuItem>
                    <asp:MenuItem Value="opt_1_3_2" Text="菜单三B">
                    </asp:MenuItem>
                    <asp:MenuItem Value="opt_1_3_3" Text="菜单三C">
                    </asp:MenuItem>
                </asp:MenuItem>
            </Items>
        </asp:Menu>
        <p>
            <asp:TextBox ID="txt1" runat="server"></asp:TextBox>
        </p>
    </form>
</body>
</html>

页面中,主菜单项有三个,分别是“菜单一”、“菜单二”和“菜单三”;然后,在“菜单三”中又定义了三个子菜单。这里,菜单由Menu控件定义,菜单项会定义在<Items>和</Items>之间,使用MenuItem类定义,并可以嵌套定义从而定义为多级菜单。

如果菜单只是导航作用,可以在MenuItem中使用NavigateUrl属性定义点击菜单项打开的地址。

本例,在Menu控件中定义了OnMenuItemClick事件的响应方法,在点击菜单项时会在txt1控件中显示点击菜单项的值(Value属性);响应方法定义如下(/demo/menu/MenuDemo.aspx.cs)。

C#
protected void menu1_MenuItemClick(object sender, MenuEventArgs e)
{
    txt1.Text = menu1.SelectedValue;
}

定义菜单的样式时,可以在Menu控件中嵌套定义如下元素。

  • StaticHoverStyle,静态菜单项在鼠标指针置于其上时的样式设置。
  • StaticMenuItemStyle,单个静态菜单项的样式设置。
  • StaticMenuStyle,静态菜单的样式设置。
  • StaticSelectedStyle,当前选定的静态菜单项的样式设置。
  • DynamicHoverStyle,动态菜单项在鼠标指针置于其上时的样式设置。
  • DynamicMenuItemStyle,单个动态菜单项的样式设置。
  • DynamicMenuStyle,动态菜单的样式设置。
  • DynamicSelectedStyle,当前选定的动态菜单项的样式设置。

这里,静态菜单是指始终显示的菜单项,动态菜单是指当鼠标指向某个菜单项后才显示的子菜单项。这些样式元素应定义在Menu控件中,Items元素之外,即样式元素和Items元素是同级的。下面的代码定义了水平方向的菜单,并使用了一些样式。

HTML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="MenuStyleDemo.aspx.cs" Inherits="demo_menu_MenuStyleDemo" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Menu ID="menu1" runat="server" Orientation="Horizontal">
            <StaticMenuItemStyle BackColor="SteelBlue" 
                ForeColor="White" Width="150"
                BorderColor="White" BorderWidth="1" />
            <DynamicMenuItemStyle BackColor="LightGray"
                 ForeColor="Black" Width="145" />
                <Items>
                <asp:MenuItem Value="opt_1_1" Text="菜单一">
                </asp:MenuItem>
                <asp:MenuItem Value="opt_1_2" Text="菜单二">
                </asp:MenuItem>
                <asp:MenuItem Value="opt_1_3" Text="菜单三">
                    <asp:MenuItem Value="opt_1_3_1" Text="菜单三A">
                    </asp:MenuItem>
                    <asp:MenuItem Value="opt_1_3_2" Text="菜单三B">
                    </asp:MenuItem>
                    <asp:MenuItem Value="opt_1_3_3" Text="菜单三C">
                    </asp:MenuItem>
                </asp:MenuItem>
            </Items>
        </asp:Menu>
    </form>
</body>
</html>

页面显示效果如图9。

图9

稍后会讨论如何通过数据绑定定义菜单内容。

多视图

当页面中的内容比较多时,可以进行分类组织,如使用MultiView控件,其中可以包括多个View组件,这些View一次只能显示一个。下面的代码(/demo/MultiViewDemo.aspx)定义了一个简单的MultiView控件。

HTML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="MultiViewDemo.aspx.cs" Inherits="demo_multiview_MultiViewDemo" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Menu ID="menu1" runat="server" 
            Orientation="Horizontal" OnMenuItemClick="menu1_MenuItemClick" >
            <Items>
                <asp:MenuItem Value="0" Text="视图一"></asp:MenuItem>
                <asp:MenuItem Value="1" Text="视图二"></asp:MenuItem>
                <asp:MenuItem Value="2" Text="视图三"></asp:MenuItem>
            </Items>
        </asp:Menu>
        <asp:MultiView ID="mv1" runat="server" ActiveViewIndex="0">
            <asp:View ID="view1" runat="server">
                <label for="txt1">文本一</label>
                <asp:TextBox ID="txt1" runat="server"></asp:TextBox>
            </asp:View>
            <asp:View ID="view2" runat="server">
                <label for="txt2">文本二</label>
                <asp:TextBox ID="txt2" runat="server"></asp:TextBox>
            </asp:View>
            <asp:View ID="view3" runat="server">
                <label for="txt3">文本三</label>
                <asp:TextBox ID="txt3" runat="server"></asp:TextBox>
            </asp:View>
        </asp:MultiView>
    </form>
</body>
</html>

页面中使用了一个水平方向的菜单进行视图的切换操作,菜单项的值(Value值)会对应视图(View)的索引。页面显示效果如图10。

图10

页面中,当点击一个菜单项时,会显示相应索引的视图,响应代码如下(/demo/MultiViewDemo.aspx.cs)。

C#
protected void menu1_MenuItemClick(object sender, MenuEventArgs e)
{
    mv1.ActiveViewIndex = tInt.GetValue(menu1.SelectedValue);
}

其中的tInt.GetValue()是本教程封装的类型转换方法,其功能是直接获取参数的int类型数据,转换失败时返回0,后续课程会有详细讨论。

除了MultiView控件的ActiveViewIndex属性,还可以使用SetActiveView()方法设置当前视图,其参数为View对象,如下面的代码。

C#
protected void menu1_MenuItemClick(object sender, MenuEventArgs e)
{
    mv1.SetActiveView(mv1.Views[tInt.Parse(menu1.SelectedValue)]);
}

向导

与多视图控件相比,向导控件体现了操作的步骤;页面中,使用Wizard控件定义向导视图,并使用WizardStep组件定义其中的一个步骤视图。下面的代码(/demo/wizard/WizardDemo.aspx)演示了Wizard和WizardStep的应用。

HTML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="WizardDemo.aspx.cs" Inherits="demo_wizard_WizardDemo" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Wizard ID="w1" runat="server" DisplaySideBar="false"
            OnPreviousButtonClick="w1_PreviousButtonClick"
            OnNextButtonClick="w1_NextButtonClick"
            OnFinishButtonClick="w1_FinishButtonClick">
            <WizardSteps>
                <asp:WizardStep ID="step1" runat="server">
                    <h1>第一步</h1>
                </asp:WizardStep>
                <asp:WizardStep ID="step2" runat="server">
                    <h1>第二步</h1>
                </asp:WizardStep>
                <asp:WizardStep ID="step3" runat="server">
                    <h1>第三步</h1>
                </asp:WizardStep>
            </WizardSteps>
        </asp:Wizard>
        <p>
            <asp:TextBox ID="txt1" runat="server"></asp:TextBox>
        </p>
    </form>
</body>
</html>

页面中创建了一个Wizard控件,并使用WizardSteps元素定义向导中的步骤,本例共定义了三个步骤,其中简单的显示了第几个步骤。

操作向导时,常用的操作包括下一步、上一步和完成,在Wizard控件中分别使用OnNextButtonClick、OnPreviousButtonClick和OnFinishButtonClick属性设置事件的响应方法。

Wizard控件的DisplaySideBar属性用于设置是否显示边栏,默认为true,会在控件的左侧显示各步骤的导航,响应边栏操作时可以使用OnSideBarButtonClick属性设置事件响应方法,本例中将不显示边栏。如果需要响应步骤变化时操作,可以使用OnActiveStepChanged属性设置响应方法。

此外,如果向导中需要使用取消按钮,可以将Wizard控件的DisplayCancelButton属性设置为true,并使用OnCancelButtonClick属性设置点击取消按钮时的响应方法。

页面中的TextBox控件(txt1)用于显示一些信息。

下面的代码(/demo/wizard/WizardDemo.aspx.cs)是上一步、下一步和完成操作的响应代码,这里只显示了一些操作信息。

C#
using System;
using System.Web.UI.WebControls;

public partial class demo_wizard_WizardDemo : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void w1_FinishButtonClick(object sender, 
        WizardNavigationEventArgs e)
    {
        if (e.CurrentStepIndex == 2)
        {
            txt1.Text = "向导操作完成";
        }
    }

    protected void w1_PreviousButtonClick(object sender, 
        WizardNavigationEventArgs e)
    {
        if (e.CurrentStepIndex == 1)
        {
            txt1.Text = "第二步返回第一步";
        }else if (e.CurrentStepIndex == 2)
        {
            txt1.Text = "第三步返回第二步";
        }
    }

    protected void w1_NextButtonClick(object sender, 
        WizardNavigationEventArgs e)
    {
        if (e.CurrentStepIndex == 0)
        {
            txt1.Text = "第一步完成,下一步";
        }else if(e.CurrentStepIndex==1)
        {
            txt1.Text = "第二步完成,下一步";
        }
    }
}

代码中,使用WizardNavigationEventArgs对象中的CurrentStepIndex属性获取当前步骤的索引值;获取下一步骤操作索引值时可以使用NextStepIndex属性。

需要注意的是,上一步操作不会出现在第一个步骤中,下一步操作不会出现在最后一个步骤中,而完成操作只在最后一个步骤中执行。

树状视图

TreeView控件用于处理树状视图,其中,节点由TreeNode对象构成,下面的代码(/demo/treenode/TreeNodeDemo.aspx)演示了TreeView和TreeNode的基本应用。

HTML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="TreeNodeDemo.aspx.cs" 
    Inherits="demo_treenode_TreeNodeDemo" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:TreeView ID="tv1" runat="server" 
            OnSelectedNodeChanged="tv1_SelectedNodeChanged">
            <Nodes>
                <asp:TreeNode Value="1_1" Text="节点1_1">
                </asp:TreeNode>
                <asp:TreeNode Value="1_2" Text="节点1_2">
                </asp:TreeNode>
                <asp:TreeNode Value="1_3" Text="节点1_3">
                    <asp:TreeNode Value="2_1" Text="节点2_1">
                    </asp:TreeNode>
                    <asp:TreeNode Value="2_2" Text="节点2_2">
                    </asp:TreeNode>
                    <asp:TreeNode Value="2_3" Text="节点2_3">
                    </asp:TreeNode>
                </asp:TreeNode>
            </Nodes>
        </asp:TreeView>
        <p>
            <asp:TextBox ID="txt1" runat="server"></asp:TextBox>
        </p>
    </form>
</body>
</html>

TreeView控件中,选择节操作的响应方法由OnSelectedNodeChanged属性指定。视图中的节点定义了<Nodes>和</Nodes> 之间,分别使用TreeNode组件定义,并且,节点可以嵌套定义。页面显示效果如图11。

图11

点击节点后,会在文本框txt1中显示节点的数据(Value属性),实现代码如下(/demo/treenode/TreeNodeDemo.aspx.cs)。

C#
using System;
using System.Web.UI.WebControls;

public partial class demo_treenode_TreeNodeDemo : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void tv1_SelectedNodeChanged(object sender, EventArgs e)
    {
        txt1.Text = tv1.SelectedValue;
    }
}

获取选择的节点时,可以使用TreeView对象的SelectedNode属性,如下面的代码可以在文本框txt1中显示选择节点的文本内容。

C#
TreeNode node = tv1.SelectedNode;
txt1.Text = node.Text;

此外,在TreeView控件中,常用的属性还包括:

  • CollapseImageUrl,设置节点收起操作图片。
  • ExpandImageUrl,设置节点展开操作图片。
  • NoExpandImageUrl,设置不能展开节点的图片,即节点没有子节点时的图片。
  • Nodes属性,第一级(Depth属性为0)的节点集合;需要注意的是,在使用TreeNode对象时,获取子节点集合需要使用ChildNodes属性。

TreeView控件常用的事件包括:

  • OnTreeNodeCollapsed,设置节点收起(折叠)时的响应方法。
  • OnTreeNodeExpanded,设置节点展开时的响应方法。

此外,需要收起(折叠)节点时使用CollapseAll()方法,展开所有节点时使用ExpandAll()方法。

使用TreeView控件时,还可以使用ShowCheckBoxes属性设置节点的复选框,其值包括:

  • None,默认值,不显示复选框。
  • All,所有节点显示复选框。
  • Leaf,所有叶节点显示复选框,有子节点的节点不显示复选框。
  • Parent,为所有父节点显示复选框。
  • Root,为所有根节点(第一级节点)显示复选框。

下面的代码(/demo/treenode/TreeNodeCheckDemo.aspx)定义了一个叶节点显示复选框的树状视图。

HTML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="TreeNodeCheckDemo.aspx.cs" 
    Inherits="demo_treenode_TreeNodeCheckDemo" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:TreeView ID="tv1" runat="server" 
            ShowCheckBoxes="Leaf">
            <Nodes>
                <asp:TreeNode Value="1_1" Text="节点1_1">
                </asp:TreeNode>
                <asp:TreeNode Value="1_2" Text="节点1_2">
                </asp:TreeNode>
                <asp:TreeNode Value="1_3" Text="节点1_3">
                    <asp:TreeNode Value="2_1" Text="节点2_1">
                    </asp:TreeNode>
                    <asp:TreeNode Value="2_2" Text="节点2_2">
                    </asp:TreeNode>
                    <asp:TreeNode Value="2_3" Text="节点2_3">
                    </asp:TreeNode>
                </asp:TreeNode>
            </Nodes>
        </asp:TreeView>
        <p>
            <asp:ListBox ID="lst1" runat="server" Width="100" Rows="10">
            </asp:ListBox>
            <asp:Button ID="btnReadChecked" Text="已选择数据" 
                runat="server" OnClick="btnReadChecked_Click" />
        </p>
    </form>
</body>
</html>

页面显示效果如图12。

图12

其中,表列lst1用于显示选中的节点数据(Value属性)。按钮btnReadChecked用于读取选中复选框的节点数据,并显示在lst1列表中。

页面的C#代码部分如下(/demo/treenode/TreeNodeCheckDemo.aspx.cs)。

C#
using System;
using System.Web.UI.WebControls;

public partial class demo_treenode_TreeNodeCheckDemo : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void btnReadChecked_Click(object sender, EventArgs e)
    {
        lst1.Items.Clear();
        foreach (TreeNode node in tv1.CheckedNodes)
            lst1.Items.Add(new ListItem(node.Value, node.Value));
    }
}

btnReadChecked_Click()方法中,通过TreeView控件的CheckedNodes属性获取复选框选中的节点集合,并在lst1列表中显示选中的节点数据,执行效果如图13。

图13

Panel控件

Panel是一种容器控件,在客户端会显示为div元素。如果一些控件需要统一操作,比如在一定条件下才显示,就可以将这些控件定义在Panel控件中,并设置Panel控件的Visible属性为false,当条件满足时再将Panel控件的Visiable属性设置为true,这样,Panel控件中的一组控件就可以一起隐藏或显示。

自动回传

很多Web控件中都有自动回传功能,如文本框内容改变时的自动回传操作、列表选择项改变时的自动回传操作等。

自动回传操作一般用于在控件数据改变时需要服务器端进行更新操作的场景,如页面中包含主列表和子列表,当主列表选项改变时,子列表需要从数据库读取数据并更新列表内容,此时,可以在主列表中使用自动回传操作,并在响应事件的方法中读取数据并更新子列表的内容。

下面的代码定义了基本的主子表结构页面。

HTML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="Test.aspx.cs" Inherits="Test" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <p>
            <label>主列表</label>
            <asp:DropDownList ID="drp1" runat="server" 
                AutoPostBack="true" 
                OnSelectedIndexChanged="drp1_SelectedIndexChanged">
                <asp:ListItem Value="1" Text="1"></asp:ListItem>
                <asp:ListItem Value="2" Text="2"></asp:ListItem>
                <asp:ListItem Value="3" Text="3"></asp:ListItem>
            </asp:DropDownList>
        </p>
        <p>
            <label>子列表</label><br />
            <asp:ListBox ID="lst1" runat="server">
                <asp:ListItem Value="11" Text="11"></asp:ListItem>
                <asp:ListItem Value="12" Text="12"></asp:ListItem>
                <asp:ListItem Value="13" Text="13"></asp:ListItem>
            </asp:ListBox>
        </p>
    </form>
</body>
</html>

页面中,drp1控件定义为DropDownList控件,其中自动回传相关属性包括:

  • AutoPostBack属性指定控件是否启用自动回传,默认为false,这里设置为true。
  • OnSelectedIndexChanged属性,指定响应自动回传事件的方法。

在页面的C#代码文件中,使用如下代码响应drp1列表的数据回传操作。

C#
protected void drp1_SelectedIndexChanged(object sender, EventArgs e)
{
    int selValue = tInt.GetValue(drp1.SelectedValue);
    lst1.Items.Clear();
    for(int i = 1; i <= 3; i++)
    {
        string s = selValue.ToString() + i.ToString();
        lst1.Items.Add(new ListItem(s, s));
    }
}

代码中,首先读取drp1列表中选中的项目数据,如本例中的1、2、3;drp1中选中新的项目后会清理lst1列表内容,然后根据drp1选中的值更新lst1列表内容,图14中显示了drp1中选中3的效果。

图14

使用控件的自动回传功能时应注意,一个控件的回传操作需要整个页面进行回调,其效率是比较低的,在并发操作不高的Web应用中可以提高开发效率,而大量的回调操作会对系统的整体执行效率有较大的负面影响。

在Web应用中,对于必须在服务器更新的数据、或者安全性要求较高的操作,可以使用自动回传,并在服务器端进行处理;如果只是相对简单的同步操作,可以在客户端使用JavaScript代码完成,同时,对于页面中只需要局部更新的数据,也可以使用Ajax完成,这样可以更加合理地组织Web应用功能,提高Web应用的整体应用效率。JavaScript、Ajax等客户端技术在ASP.NET项目中的应用可以参考《网站全栈开发指南:HTML+CSS+JavaScript+ASP.NET》一书。