添加 GridView 复选框列 (C#)

作者 :Scott Mitchell

下载 PDF

本教程介绍如何将一列检查框添加到 GridView 控件,以便为用户提供一种直观的方式来选择 GridView 的多行。

简介

在前面的教程中,我们了解了如何向 GridView 添加一列单选按钮,以便选择特定记录。 当用户最多只能从网格中选择一项时,单选按钮列是合适的用户界面。 但是,有时,我们可能希望允许用户从网格中选取任意数量的项。 例如,基于 Web 的电子邮件客户端通常显示带有一列复选框的邮件列表。 用户可以选择任意数量的邮件,然后执行一些操作,例如将电子邮件移动到另一个文件夹或删除它们。

在本教程中,我们将了解如何添加一列复选框,以及如何确定在回发时选中的复选框。 具体而言,我们将生成一个示例,以密切模拟基于 Web 的电子邮件客户端用户界面。 我们的示例将包含一个分页的 GridView,其中列出了数据库表中的产品 Products ,每行都有一个复选框 (请参阅图 1) 。 单击“删除所选产品”按钮将删除所选产品。

每个产品行包含一个复选框

图 1:每个产品行包含一个复选框 (单击以查看全尺寸图像)

步骤 1:添加Lists产品信息的分页 GridView

在担心添加一列复选框之前,让我们首先重点介绍在支持分页的 GridView 中列出产品。 首先打开 文件夹中的页面CheckBoxField.aspxEnhancedGridView,并将 GridView 从“工具箱”拖到Designer,将其ID设置为 Products。 接下来,选择将 GridView 绑定到名为 ProductsDataSource的新 ObjectDataSource。 将 ObjectDataSource 配置为使用 ProductsBLL 类,调用 GetProducts() 方法以返回数据。 由于此 GridView 将是只读的,因此请将“更新”、“插入”和“删除”选项卡中的下拉列表设置为 (None) 。

新建名为 ProductsDataSource 的 ObjectDataSource

图 2:创建名为 ProductsDataSource 的新对象DataSource (单击以查看全尺寸图像)

配置 ObjectDataSource 以使用 GetProducts () 方法检索数据

图 3:使用 GetProducts() 方法配置 ObjectDataSource 以检索数据 (单击以查看全尺寸图像)

将“更新”、“插入”和“删除”选项卡中的 Drop-Down Lists 设置为“ (None”)

图 4:将“更新”、“插入”和“删除”选项卡中的 Drop-Down Lists 设置为“无 () (单击以查看全尺寸图像)

完成“配置数据源”向导后,Visual Studio 将自动为与产品相关的数据字段创建 BoundColumns 和 CheckBoxColumn。 与上一教程中一样,删除除 ProductNameCategoryNameUnitPrice BoundField 之外的所有字段,并将 HeaderText 属性更改为“产品”、“类别”和“价格”。 配置 UnitPrice BoundField,使其值的格式设置为货币。 此外,通过选中智能标记中的“启用分页”复选框,将 GridView 配置为支持分页。

我们还添加用于删除所选产品的用户界面。 在 GridView 下添加一个按钮 Web 控件,将其 ID 设置为 DeleteSelectedProducts ,将其 Text 属性设置为“删除所选产品”。 对于本示例,我们将仅显示一条消息,指出将删除的产品,而不是实际从数据库中删除产品。 若要适应这种情况,请在“按钮”下面添加一个标签 Web 控件。 将其 ID 设置为 DeleteResults,清除其 Text 属性,并将其 VisibleEnableViewState 属性设置为 false

进行这些更改后,GridView、ObjectDataSource、Button 和 Label 声明性标记应类似于以下内容:

<p>
    <asp:GridView ID="Products" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
        AllowPaging="True" EnableViewState="False">
        <Columns>
            <asp:BoundField DataField="ProductName" HeaderText="Product" 
                SortExpression="ProductName" />
            <asp:BoundField DataField="CategoryName" HeaderText="Category" 
                ReadOnly="True" SortExpression="CategoryName" />
            <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" 
                HeaderText="Price" HtmlEncode="False" 
                SortExpression="UnitPrice" />
        </Columns>
    </asp:GridView>
    <asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}" 
        SelectMethod="GetProducts" TypeName="ProductsBLL">            
    </asp:ObjectDataSource>
</p>
<p>
    <asp:Button ID="DeleteSelectedProducts" runat="server" 
        Text="Delete Selected Products" />
</p>
<p>
    <asp:Label ID="DeleteResults" runat="server" EnableViewState="False" 
        Visible="False"></asp:Label>
</p>

花点时间在浏览器中查看页面, (请参阅图 5) 。 此时,应会看到前十个产品的名称、类别和价格。

列出了前十个产品的名称、类别和价格

图 5:列出前十个产品的名称、类别和价格 (单击以查看全尺寸图像)

步骤 2:添加复选框列

由于 ASP.NET 2.0 包含 CheckBoxField,因此人们可能会认为它可用于向 GridView 添加一列复选框。 遗憾的是,情况并非如此,因为 CheckBoxField 旨在处理布尔数据字段。 也就是说,若要使用 CheckBoxField,必须指定基础数据字段,以便查询其值以确定是否选中呈现的复选框。 我们不能使用 CheckBoxField 仅包含一列未选中的复选框。

相反,我们必须添加 TemplateField 并将 CheckBox Web 控件添加到其 ItemTemplate中。 继续操作,将 TemplateField 添加到 Products GridView,使其成为最左侧) 字段的第一 (。 在 GridView 智能标记中,单击“编辑模板”链接,然后将 CheckBox Web 控件从“工具箱”拖动到 。ItemTemplate 将此 CheckBox 属性 ID 设置为 ProductSelector

将名为 ProductSelector 的 CheckBox Web 控件添加到 TemplateField 的 ItemTemplate

图 6:将名为 的 ProductSelector CheckBox Web 控件添加到 TemplateField (ItemTemplate单击以查看全尺寸图像)

添加 TemplateField 和 CheckBox Web 控件后,每行现在都包含一个复选框。 图 7 显示了在添加 TemplateField 和 CheckBox 后通过浏览器查看的此页面。

每个产品行现在包含一个复选框

图 7:每个产品行现在包含一个复选框 (单击以查看全尺寸图像)

步骤 3:确定在回发时选中了哪些复选框

此时,我们有一列复选框,但无法确定在回发时选中的复选框。 不过,单击“删除所选产品”按钮时,我们需要知道选中了哪些复选框才能删除这些产品。

GridView 属性Rows提供对 GridView 中的数据行的访问权限。 我们可以循环访问这些行,以编程方式访问 CheckBox 控件,然后查阅其 Checked 属性以确定 CheckBox 是否已选中。

DeleteSelectedProducts Button Web 控件 事件 Click 创建事件处理程序,并添加以下代码:

protected void DeleteSelectedProducts_Click(object sender, EventArgs e)
{
    bool atLeastOneRowDeleted = false;
    // Iterate through the Products.Rows property
    foreach (GridViewRow row in Products.Rows)
    {
        // Access the CheckBox
        CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
        if (cb != null && cb.Checked)
        {
            // Delete row! (Well, not really...)
            atLeastOneRowDeleted = true;
            // First, get the ProductID for the selected row
            int productID = 
                Convert.ToInt32(Products.DataKeys[row.RowIndex].Value);
            // "Delete" the row
            DeleteResults.Text += string.Format(
                "This would have deleted ProductID {0}<br />", productID);
        }
    }
    // Show the Label if at least one row was deleted...
    DeleteResults.Visible = atLeastOneRowDeleted;
}

属性 Rows 返回构成 GridView 数据行的实例集合 GridViewRow 。 此处的 foreach 循环枚举此集合。 对于每个 GridViewRow 对象,使用 以编程方式访问 row.FindControl("controlID")行 CheckBox。 如果选中了 CheckBox,则从集合中检索行对应的ProductIDDataKeys值。 在本练习中,我们只是在 Label 中 DeleteResults 显示一条信息性消息,但在工作应用程序中,我们将改为调用 ProductsBLL 类的 方法 DeleteProduct(productID)

添加此事件处理程序后,单击“删除所选产品”按钮现在会显示 ProductID 所选产品的 。

单击“删除所选产品”按钮时,将列出所选产品的产品ID

图 8:单击“删除所选产品”按钮时,“所选产品 ProductID ”将列出 (单击以查看全尺寸图像)

步骤 4:添加“全部选中”和“取消选中所有”按钮

如果用户想要删除当前页面上的所有产品,则必须检查十个复选框中的每一个。 我们可以通过添加“全部选中”按钮来帮助加快此过程,单击该按钮时会选中网格中的所有复选框。 “取消选中所有”按钮同样有用。

将两个按钮 Web 控件添加到页面,将它们放置在 GridView 上方。 将第一个 设置为 ,CheckAllID将其 Text 属性设置为 Check All;将第二个 设置为 ,IDUncheckAll将其 Text 属性设置为 Uncheck All 。

<asp:Button ID="CheckAll" runat="server" Text="Check All" />
 
<asp:Button ID="UncheckAll" runat="server" Text="Uncheck All" />

接下来,在名为 的代码隐藏类中创建一个 ToggleCheckState(checkState) 方法,该方法在调用时枚举 Products GridView 的 Rows 集合,并将每个 CheckBox 属性 Checked 设置为传入的 checkState 参数的值。

private void ToggleCheckState(bool checkState)
{
    // Iterate through the Products.Rows property
    foreach (GridViewRow row in Products.Rows)
    {
        // Access the CheckBox
        CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
        if (cb != null)
            cb.Checked = checkState;
    }
}

接下来,为 CheckAllUncheckAll 按钮创建Click事件处理程序。 在 CheckAll 事件处理程序中,只需调用 ToggleCheckState(true);在 中 UncheckAll,调用 ToggleCheckState(false)

protected void CheckAll_Click(object sender, EventArgs e)
{
    ToggleCheckState(true);
}
protected void UncheckAll_Click(object sender, EventArgs e)
{
    ToggleCheckState(false);
}

使用此代码,单击“全部选中”按钮会导致回发,并检查 GridView 中的所有复选框。 同样,单击“全部取消选中”将取消选中所有复选框。 图 9 显示了选中“全部检查”按钮后的屏幕。

单击“全部选中”按钮选择所有复选框

图 9:单击“全部选中”按钮选中所有复选框 (单击以查看全尺寸图像)

注意

显示一列复选框时,选择或取消选中所有复选框的一种方法是通过标题行中的复选框。 此外,当前的 Check All/Uncheck All 实现需要回发。 但是,可以完全通过客户端脚本选中或取消选中复选框,从而提供快速的用户体验。 若要详细了解如何使用“全部选中”和“全部取消选中”的标题行复选框,以及有关使用客户端技术的讨论,检查使用 Client-Side 脚本签出 GridView 中的所有 CheckBox 和 Check All CheckBox

总结

如果需要让用户在继续操作之前从 GridView 中选择任意数量的行,则添加一列复选框是其中一个选项。 正如我们在本教程中看到的,在 GridView 中包含一列复选框需要添加带有 CheckBox Web 控件的 TemplateField。 通过使用 Web 控件 (而不是直接将标记注入到模板中,正如我们在上一教程中所做的那样,) ASP.NET 会自动记住 CheckBox 是什么,并且不会在回发中检查。 我们还可以以编程方式在代码中访问 CheckBox,以确定是否选中了给定的 CheckBox 或更改选中状态。

本教程和上一篇教程介绍了如何将行选择器列添加到 GridView。 在下一教程中,我们将探讨如何通过一些工作向 GridView 添加插入功能。

编程愉快!

关于作者

Scott Mitchell 是七本 ASP/ASP.NET 书籍的作者, 4GuysFromRolla.com 的创始人,自 1998 年以来一直从事 Microsoft Web 技术工作。 Scott 担任独立顾问、培训师和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 2.0自学。 可以在 上联系 mitchell@4GuysFromRolla.com他, 也可以通过他的博客联系到他,该博客可在 http://ScottOnWriting.NET中找到。