65.9K
CodeProject 正在变化。 阅读更多。
Home

GroupedGridview - 自定义 GridView 控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (27投票s)

2009年1月10日

CPOL

2分钟阅读

viewsIcon

107291

downloadIcon

3552

在 GridView 控件中对重复数据进行分组。

引言

本文是关于创建一个自定义的 GridView 控件,它在数据以分层格式呈现的情况下非常有用,例如,对于像国家、州等列,或者经理、雇员等列。

UnGrouped.JPG

示例数据

Grouped Image with Grouped Depth 2

分组数据

在上述情况下,可以使用 GroupedGridview 代替 GridView,它可以避免数据的重复。

背景

具备创建继承(自定义)控件知识的用户可以轻松使用/理解本文。

快速学习如何创建一个继承(自定义)控件

就像添加任何其他控件(如 ButtonDataGrid)一样。首先,创建一个新的类库项目。创建一个类并从现有类派生它。例如:TextBoxButton 等。在本文中,我们是从 GridView 类派生的。

然后,编写您想要添加的功能。这包括重写方法等。完成此操作后,创建其 DLL。在 Web 应用程序中添加对 DLL 的引用。

现在,您可以自定义工具箱了:右键单击工具箱,选择“.NET Framework 组件”,点击“浏览”,选择新创建的 DLL,然后单击“确定”。 然后,您会注意到工具箱中添加了新的控件。 现在可以使用它了。

使用代码

本文的主要部分是 GroupedGridView 类,它继承自 GridView 类。

/// <summary />
/// Summary description for GroupedGridView
/// </summary />
namespace CommonClassLibrary
{
    public class GroupedGridView : GridView
    {
       //..............
       //..............
     }
}

该类有一个属性 GroupedDepth,用于指定需要分组的列数。

public int GroupedDepth
{
    get
    {
        object val = this.ViewState["GroupedDepth"];
        if (null == val)
        {
            return 0;
        }

        return (int)val;
    }
    set
    {
        if (value < 0)
            throw new ArgumentOutOfRangeException....
        this.ViewState["GroupedDepth"] = value;
    }
}

GroupedGridView 类重写了 GridViewOnDataBound 事件,在该事件中调用了一个递归函数 SpanCellsRecursive

protected override void OnDataBound(EventArgs e)
{
    base.OnDataBound(e);
    this.SpanCellsRecursive(0, 0, this.Rows.Count);
}

下面的函数循环遍历行数据并比较列值。 比较后的值将存储在一个布尔变量 isNewGroup 中。 如果变量值为 true,则其 RowSpan 设置为 1。 并且,如果其值为 false,则单元格的 Visible 属性设置为 false 并且 RowSpan 递增,从而避免重复显示。

private void SpanCellsRecursive(int columnIndex, int startRowIndex, int endRowIndex)
{
    if (columnIndex >= this.GroupedDepth || columnIndex >= this.Columns.Count)
        return;

    TableCell groupStartCell = null;
    int groupStartRowIndex = startRowIndex;

    for (int i = startRowIndex; i < endRowIndex; i++)
    {
        TableCell currentCell = this.Rows[i].Cells[columnIndex];

        bool isNewGroup = (null == groupStartCell) || 
            (0 != String.CompareOrdinal(currentCell.Text, groupStartCell.Text));

        if (isNewGroup)
        {
            if (null != groupStartCell)
            {
                SpanCellsRecursive(columnIndex + 1, groupStartRowIndex, i);
            }

            groupStartCell = currentCell;
            groupStartCell.RowSpan = 1;
            groupStartRowIndex = i;
        }
        else
        {
            currentCell.Visible = false;
            groupStartCell.RowSpan += 1;
        }
    }
}

将类添加到类库后,添加对 DLL 的引用,控件将在工具箱中可用,可以添加到 Web 应用程序中,如上文背景部分所述。 在您的网页上新创建的控件如下所示

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

<%@ Register Assembly="CommonClassLibrary" 
   Namespace="CommonClassLibrary" TagPrefix="cc1" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head  runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1"  runat="server">
        
<div>
        <cc1:GroupedGridView ID="GroupedGridView1"  runat="server" 
          BackColor="White" BorderColor="#CCCCCC"
          BorderStyle="None" BorderWidth="1px" 
          CellPadding="3" GroupedDepth="2" AutoGenerateColumns="false">
             <columns />
                <asp:BoundField HeaderText="Country" DataField="Country" />
                <asp:BoundField HeaderText="Country Code" DataField="Code" />
                <asp:BoundField HeaderText="State" DataField="State" />
             </columns />
</div>

    </form>
</body>
</html>

注意:此控件不适用于 AutoGenerateColumns="true"。 很抱歉。 我正在处理这个问题。

//
//Binding the dataset to the Gridview
//
GroupedGridView1.DataSource = dataSet;
GroupedGridView1.DataBind();

结论

这是我的第一篇文章。 我希望您觉得这篇文章和控件有用 - 在处理几种不同类型的分层数据时,它可以节省我大量时间,从而快速启动并运行功能齐全的 GridView 分组控件。 尽情享用!

非常感谢任何改进的建议和反馈!

© . All rights reserved.