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

交叉制表报告:动态向网格添加列

starIconstarIconemptyStarIconemptyStarIconemptyStarIcon

2.00/5 (5投票s)

2007年9月10日

2分钟阅读

viewsIcon

39729

downloadIcon

529

文章描述了如何在运行时动态地向网格添加列。

引言

我们很多人可能已经使用网格在 asp .net 中显示报表。 通常,当我们在网格中显示报表时,列数将是固定的。 可以在报表中出现的行可能取决于很多因素。 交叉表报表是指行以及列数将根据用户提供的条件而变化的报表。 因此,当您使用网格显示这些类型的报表时,您必须动态地构建列。

背景

为了更清楚地解释,让我们用一个例子来演示。 在这里,你有一个简单的数据库,其中在不同的系有 'n' 个学生在一个表中,他们的分数在另一个表中。 当我说他们来自不同的系时,我的意思是他们学习的科目数量也会不同。 假设系 1 有 2 个科目,系 2 有 1 个科目。 因此,在系 1 学生的成绩单中,你可以看到科目 1 和科目 2 的分数。 而在系 2 学生的成绩单中,你只能看到一个科目的分数。

使用代码

Screenshot - CrossStar.jpg

让我们看看如何构建我们的业务对象。 我们需要一个“科目”业务对象来保存他的分数,以及一个“学生”业务对象,包含他的名字和分数列表。 它可以像这样:

Screenshot - CrossStarExample.jpg

因此,为了填充对象,我们需要先填充学生的数据,然后创建科目的对象并将其添加到分数列表的列表中。 对于交叉表实现,我们可以将此对象作为网格的数据源。 然后在绑定之前,我们可以动态地添加需要的列。

对于绑定字段,我们可以直接分配它的标题文本和数据字段。

Private Function GetBoundColumn(ByVal hText As String, ByVal datafield As String) As BoundField 

  Dim newColumn As BoundField 
       newColumn = New BoundField() 

              With newColumn 
                     .HeaderText = hText 
                     .DataField = datafield 
              End With 
       
       Return newColumn
End Function

对于模板列,我们需要使用一个实现 ITemplate 接口的类。

Private Function GetTemplateColumn(ByVal dSource As List(Of Types), ByVal colId As Integer) As TemplateField 

Dim newColumn As TemplateField 
       newColumn = New TemplateField() 
       
       With newColumn 
              .HeaderTemplate = New TemplateFactory("M" & colId, DataControlRowType.Header, 0) 
              .ItemTemplate = New TemplateFactory("", DataControlRowType.DataRow, colId) 
       End With 

       Return newColumn 
End Function

Public Class TemplateFactory 
              Implements ITemplate 

Dim _hdrName As String 
Dim _rowType As DataControlRowType 
Dim _colId As Integer 

Public Sub New(ByVal hdrName As String, ByVal rowType As DataControlRowType, ByVal colId As Integer) 
       _hdrName = hdrName 
       _rowType = rowType 
       _colId = colId 
End Sub 

Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) Implements System.Web.UI.ITemplate.InstantiateIn 
       If (_rowType = DataControlRowType.Header) Then 
              Dim oLabel As New Label() 
              
              oLabel.Text = _hdrName 
              oLabel.ForeColor = Drawing.Color.White 
              container.Controls.Add(oLabel) 
       ElseIf (_rowType = DataControlRowType.DataRow) Then 
              Dim oTextBox As New TextBox() 

              oTextBox.ID = _colId 
              AddHandler oTextBox.DataBinding, AddressOf TextBox1_DataBinding 
              container.Controls.Add(oTextBox) 
       End If 
End Sub 

Protected Sub TextBox1_DataBinding(ByVal sender As Object, ByVal e As System.EventArgs) 
Dim txt As TextBox 
Dim gvRow As GridViewRow 
Dim i As Integer 

           txt = CType(sender, TextBox) 
           gvRow = CType(txt.NamingContainer, GridViewRow) 
           i = CType(txt.ID, Integer) 

    If (CType(gvRow.DataItem, TypesList).TypeList.Count > i) Then 
              txt.Text = DataBinder.Eval(CType(gvRow.DataItem, TypesList).TypeList(i), "Name") 
           End If 

End Sub 
End Class

关注点

如果我们有很多报表需要交叉表实现,那么我们可以采用“Builder”设计模式来简化实现。 有关这方面的更多详细信息可以在附件中找到。

历史

在此处保持您所做的任何更改或改进的实时更新。

© . All rights reserved.