C# Asp.NETGridView中的数据分组

C# Asp.NETGridView中的数据分组,c#,asp.net,gridview,C#,Asp.net,Gridview,我有两个存储过程,它们返回两组相关数据。数据是这样的。 第一个过程返回如下数据 ISSUE_ID ISSUETYPE ------------------------------------- 1 ISSUE 1 TYPE 2 ISSUE 2 TYPE 3 ISSUE 3 TYPE 4 ISSUE 4 TYPE 第二个过程根据问题ID返回如下数据 HEADER ID

我有两个存储过程,它们返回两组相关数据。数据是这样的。 第一个过程返回如下数据

ISSUE_ID          ISSUETYPE          
-------------------------------------
1            ISSUE 1 TYPE
2            ISSUE 2 TYPE
3            ISSUE 3 TYPE
4            ISSUE 4 TYPE
第二个过程根据问题ID返回如下数据

HEADER ID          HEADER NAME            ISSUE_ID       
-----------------------------------------------------
 1                 HEADER 1 NAME               1   
 2                 HEADER 2 NAME               1
 3                 HEADER 3 NAME               2   
 4                 HEADER 4 NAME               2   
 5                 HEADER 5 NAME               3
问题是如何根据
ISSUE\u ID
将其分组,并使用这两个存储过程在gridview中分组显示。我在很多论坛上搜索过,发现选项是嵌套的gridview。我可以在不使用嵌套gridview的情况下实现这一点

最后,我想在gridview中显示如下内容

ISSUE 1 TYPE
-----------------------------
            HEADER 1 NAME                 
            HEADER 2 NAME 
ISSUE 2 TYPE
-----------------------------
            HEADER 3 NAME                 
            HEADER 4 NAME                  
ISSUE 3 TYPE
-----------------------------
            HEADER 5 NAME                 
提前感谢一百万。。需要一些建议来实现这一点

ASP.Net GridView中的分组示例

首先,我们创建GridViewHelper设置它将在构造函数中操作的网格。然后注册摘要,指定列名和要执行的摘要操作。结果如下:

在此示例中,添加了一个新行以显示摘要。另一个选项是使用页脚行显示摘要,而不是创建新的摘要。向网格中添加新行时,仅创建显示汇总列所需的单元格。使用页脚创建所有单元格。对于组摘要,生成所有单元格或仅生成所需单元格是组属性

现在我们将创建一个组。代码如下所示:

protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    helper.RegisterGroup("ShipRegion", true, true);
    helper.ApplyGroupSort();
}
RegisterGroup方法的第一个参数定义必须为其创建组的列。还可以创建一个由列数组组成的复合组。第二个参数指定组是否为自动组。在这种情况下,将自动为组标题创建新行。第三个参数指定是否必须隐藏组列。ApplyGroupSort方法将网格的排序表达式设置为组列,在本例中为ShipRegion。这是分组正常工作所必需的,除非数据是从数据库排序的

在上面的示例中,列ShipRegion已隐藏:

让我们做一些更有趣的事情,让我们为创建的组添加一个摘要。我们只需再增加一行即可向小组注册摘要:

protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    helper.RegisterGroup("ShipRegion", true, true);
    helper.RegisterSummary("ItemTotal", SummaryOperation.Sum, "ShipRegion");
    helper.ApplyGroupSort();
}
这次,RegisterSummary方法接受另一个参数。该参数指定必须为其创建摘要的组的名称。组名是根据组列名自动生成的。如果组只有一列,则组名将是该列的名称。如果组有多个列,则组名将是组成组的列的有序连接,并用加号(“+”)连接:“ShipRegion+ShipName”

我们可以在下面的网格中看到分组和组摘要:

protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    helper.RegisterGroup("ShipRegion", true, true);
    helper.RegisterSummary("ItemTotal", SummaryOperation.Sum, "ShipRegion");
    helper.ApplyGroupSort();
}

可以在网格中创建多个组,模拟分层分组,如下所示:

protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    helper.RegisterGroup("ShipRegion", true, true);
    helper.RegisterGroup("ShipName", true, true);
    helper.ApplyGroupSort();
}
结果:

当存在多个组时,可视化会受到影响。GridViewHelper具有允许轻松实现视觉或功能调整的事件。活动清单如下:

  • GroupStart:在新组启动时发生,这意味着在组列中找到新值时
  • GroupEnd:发生在组的最后一行
  • GroupHeader:为组添加自动标题行时发生。如果组不是自动的,则不会触发该事件
  • GroupSummary:为组生成摘要行时发生。如果该组不是自动组,则不会触发该事件,但如果该组是抑制组,则会触发该事件(稍后将看到)
  • 一般摘要:在计算一般摘要之后发生。如果摘要是自动的,则事件发生在添加摘要行和将摘要值放入该行之后
  • 页脚数据绑定:在页脚数据绑定中发生
通过几行代码,我们可以改善网格的视觉效果:

protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    helper.RegisterGroup("ShipRegion", true, true);
    helper.RegisterGroup("ShipName", true, true);
    helper.GroupHeader += new GroupEvent(helper_GroupHeader);
    helper.ApplyGroupSort();
}

private void helper_GroupHeader(string groupName, object[] values, GridViewRow row)
{
    if ( groupName == "ShipRegion" )
    {
        row.BackColor = Color.LightGray;
        row.Cells[0].Text = "  " + row.Cells[0].Text;
    }
    else if (groupName == "ShipName")
    {
        row.BackColor = Color.FromArgb(236, 236, 236);
        row.Cells[0].Text = "     " + row.Cells[0].Text;
    }
}
化妆品后的网格:

更多分组选项

还有两个有趣的例子。第一个是复合群。第二个定义了一个suppress组,其行为与SQLGROUPBY子句相同。将抑制重复值,并对其他列执行摘要操作

下面我们可以看到复合组的代码和网格外观:

protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    string[] cols = new string[2];
    cols[0] = "ShipRegion";
    cols[1] = "ShipName";
    helper.RegisterGroup(cols, true, true);
    helper.ApplyGroupSort();
}

我们可以在小组中添加摘要。这次我们将定义一个平均操作,并添加一个标签来指示该操作:

protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    string[] cols = new string[2];
    cols[0] = "ShipRegion";
    cols[1] = "ShipName";
    helper.RegisterGroup(cols, true, true);
    helper.RegisterSummary("ItemTotal", SummaryOperation.Avg, "ShipRegion+ShipName");
    helper.GroupSummary += new GroupEvent(helper_GroupSummary);
    helper.ApplyGroupSort();
}

private void helper_GroupSummary(string groupName, object[] values, GridViewRow row)
{
    row.Cells[0].HorizontalAlign = HorizontalAlign.Right;
    row.Cells[0].Text = "Average";
}

最后一个示例将创建一个抑制组。必须指出的是,如果定义了抑制组,则不能创建其他组。同样,如果已经定义了一个组,我们不能创建一个抑制组,如果我们尝试它,将引发一个异常

下面我们可以看到抑制组的代码和网格外观:

protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    helper.SetSuppressGroup("ShipName");
    helper.RegisterSummary("Quantity", SummaryOperation.Sum, "ShipName");
    helper.RegisterSummary("ItemTotal", SummaryOperation.Sum, "ShipName");
    helper.ApplyGroupSort();
}

对于未定义摘要操作的列,不显示任何值。这很有意义,因为GridViewHelper不知道如何将组行中的值汇总为唯一值。这提醒了某些已知的信息:

“列‘Column_name’在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。”

显示没有摘要操作的列是没有意义的,要隐藏它们,我们需要调用一个方法:

protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    helper.SetSuppressGroup(rdBtnLstGroup.SelectedValue);
    helper.RegisterSummary("Quantity", SummaryOperation.Sum, "ShipName");
    helper.RegisterSummary("ItemTotal", SummaryOperation.Sum, "ShipName");
    helper.SetInvisibleColumnsWithoutGroupSummary();
    helper.ApplyGroupSort();
}
我知道,这是个大名字!生成的网格如下所示:

protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    helper.RegisterGroup("ShipRegion", true, true);
    helper.RegisterGroup("ShipName", true, true);
    helper.ApplyGroupSort();
}

摘要操作

GridViewHelper有三个内置的摘要操作:求和、平均和行计数。一个非常有用的功能是可以定义自定义摘要操作。为了实现这一点,我们需要为GridViewHelper提供两种方法。将为网格(或组)中找到的每一行调用一个方法,并调用另一个方法来检索
private List<int> mQuantities = new List<int>();

protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    helper.RegisterSummary("Quantity", SaveQuantity, GetMinQuantity);
}

private void SaveQuantity(string column, string group, object value)
{
    mQuantities.Add(Convert.ToInt32(value));
}

private object GetMinQuantity(string column, string group)
{
    int[] qArray = new int[mQuantities.Count];
    mQuantities.CopyTo(qArray);
    Array.Sort(qArray);
    return qArray[0];
}
protected void Page_Load(object sender, EventArgs e)
{
    GridViewHelper helper = new GridViewHelper(this.GridView1);
    helper.RegisterGroup("ShipRegion", true, true);
    helper.RegisterGroup("ShipName", true, true);
    helper.RegisterSummary("ItemTotal", SummaryOperation.Sum, "ShipName");
    helper.RegisterSummary("ItemTotal", SummaryOperation.Sum);
    helper.GroupSummary += new GroupEvent(helper_Bug);
    helper.ApplyGroupSort();
}

private void helper_Bug(string groupName, object[] values, GridViewRow row)
{
    if (groupName == null) return;

    row.BackColor = Color.Bisque;
    row.Cells[0].HorizontalAlign = HorizontalAlign.Center;
    row.Cells[0].Text = "[ Summary for " + groupName + " " + values[0] + " ]";
}
Group1_Start
Group1_End
Group2_Start
Group2_End
Group1_Start
Group2_Start
Group2_End
Group1_End
public GridViewHelper(GridView grd, bool useFooterForGeneralSummaries, SortDirection groupSortDirection)
{
    this.mGrid = grd;
    this.useFooter = useFooterForGeneralSummaries;
    this.groupSortDir = groupSortDirection;
    this.mGeneralSummaries = new GridViewSummaryList();
    this.mGroups = new GridViewGroupList();
    this.mGrid.RowDataBound += new GridViewRowEventHandler(RowDataBoundHandler);
}
readonly Dictionary<Control, string> _groupNames = new Dictionary<Control, string>();
private Group _lastGroup;
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        var obj = (Obj)e.Row.DataItem;
        if (obj.Group != _lastGroup)
        {
            e.Row.SetRenderMethodDelegate(RenderGridViewRowWithHeader);
            _lastGroup = obj.Group;

            // Cache group description for this row, note that you might
            // like to implement this differently if you have your data normalized.
            _groupNames[e.Row] = obj.Group.Description;                 }
        }
    }
}
private void RenderGridViewRowWithHeader(HtmlTextWriter output, Control container)
{
    // Render group header
    var row = new TableRow { CssClass = "groupingCssClass" };
    row.Cells.Add(new TableCell());
    row.Cells.Add(new TableCell
    {
        ColumnSpan = ((GridViewRow)container).Cells.Count - 1,
        Text = _groupNames[container]
    });
    row.RenderControl(output);

    // Render row
    container.SetRenderMethodDelegate(null); // avoid recursive call
    container.RenderControl(output);
}