我有一个动态创建的数据绑定网格视图。数据源根据几个 DropDownLists 返回一个对象(对象类型不同)。根据对象的类型,GridView 必须显示特定于对象的某些字段。此外,还有一个 DropDownList,其 SelectedValue 决定对象的哪些列将从 GridView 中添加/排除。
这是创建 GridView 的方法(我用 VB.NET 编写,但也非常欢迎使用 C#):
Private Sub CreateGridView()
Dim gv As New GridView
With gv
.AllowSorting = True
.AutoGenerateColumns = False
.CssClass = "gv"
.EmptyDataText = "The list is empty"
.ID = "gv"
.ShowFooter = True
.AlternatingRowStyle.Wrap = False
.EditRowStyle.Wrap = False
.FooterStyle.Wrap = False
.HeaderStyle.Wrap = False
.SortedAscendingCellStyle.CssClass = "sortAscCell"
.SortedAscendingHeaderStyle.CssClass = "sortAscHeader"
.SortedDescendingCellStyle.CssClass = "sortDescCell"
.SortedDescendingHeaderStyle.CssClass = "sortDescHeader"
AddHandler .RowDataBound, AddressOf gv_RowDataBound
AddHandler .DataBound, AddressOf gv_DataBound
AddHandler .RowUpdating, AddressOf gv_RowUpdating
.DataSource = odsEquipment.Select
.DataKeyNames = {"equipmentID"}
End With
For Each item As Dictionary In odsDictionary.Select
If ddlStages.SelectedValue <> "" Then
If ddlStages.SelectedValue >= item.stage_id Then
Dim tf As New TemplateField()
tf.SortExpression = item.col
tf.HeaderTemplate = New GridViewTemplate(item.title, item.col)
tf.ItemTemplate = New GridViewTemplate(DataControlRowType.DataRow, item.col, item.ctrlType, item.length)
tf.FooterTemplate = New GridViewTemplate(DataControlRowType.Footer, item.col, item.ctrlType, item.length)
gv.Columns.Add(tf)
End If
End If
Next
gv.DataBind()
divGV.Controls.Add(gv)
End Sub
GridView 始终处于编辑模式,这意味着它的 ItemTemplate 是 TexBox/DropDownList/CheckBox。这是一个 ITemplate 类:
Imports System.Data
Public Class GridViewTemplate
Implements ITemplate
Private templateType As DataControlRowType
Private title As String
Private columnBinding As String
Private ctrlType As String
Private length As Integer
Public Sub New(ByVal vTitle As String, vColumnBinding As String)
templateType = DataControlRowType.Header
title = vTitle
columnBinding = vColumnBinding
End Sub
Public Sub New(ByVal type As DataControlRowType, ByVal vColumnBinding As String, ByVal vCtrlType As String, vLength As Integer)
templateType = type
columnBinding = vColumnBinding
ctrlType = vCtrlType
length = vLength
End Sub
Private Sub InstantiateIn(container As Control) Implements ITemplate.InstantiateIn
Select Case templateType
Case DataControlRowType.Header
Dim lb As New LinkButton()
lb.ID = "lb" + columnBinding
lb.CommandName = "Sort"
lb.CommandArgument = columnBinding
lb.Text = title
container.Controls.Add(lb)
Exit Select
Case DataControlRowType.DataRow
If ctrlType = "Label" Then
Dim lbl = New Label()
lbl.ID = "lbl" + columnBinding
AddControl(lbl, container)
ElseIf ctrlType = "TextBox" Then
Dim tb As New TextBox
tb.ID = "tb" + columnBinding
tb.MaxLength = length
AddControl(tb, container)
ElseIf ctrlType = "CheckBox" Then
Dim cb = New CheckBox()
cb.ID = "cb" + columnBinding
AddControl(cb, container)
ElseIf ctrlType = "DropDownList" Then
Dim ddl = New DropDownList()
ddl.ID = "ddl" + columnBinding
AddControl(ddl, container)
End If
Exit Select
Case DataControlRowType.Footer
If ctrlType = "Label" Then
Dim tbFrom As New TextBox()
tbFrom.ID = "tb" + columnBinding + "From"
container.Controls.Add(tbFrom)
Dim tbTo As New TextBox()
tbTo.ID = "tb" + columnBinding + "From"
container.Controls.Add(tbTo)
ElseIf ctrlType = "TextBox" Then
Dim tb As New TextBox
tb.ID = "tb" + columnBinding
tb.MaxLength = length
container.Controls.Add(tb)
ElseIf ctrlType = "CheckBox" Then
Dim cb = New CheckBox()
cb.ID = "cb" + columnBinding
container.Controls.Add(cb)
ElseIf ctrlType = "DropDownList" Then
Dim ddl = New DropDownList()
ddl.ID = "ddl" + columnBinding
AddControl(ddl, container)
End If
Exit Select
Case Else
Exit Select
End Select
End Sub
Private Sub AddControl(ctrl As Control, container As Control)
AddHandler ctrl.DataBinding, AddressOf OnDataBinding
container.Controls.Add(ctrl)
End Sub
Private Sub OnDataBinding(ByVal sender As Object, ByVal e As EventArgs)
If sender.GetType = GetType(Label) Then
Dim lb As Label = DirectCast(sender, Label)
Dim container As GridViewRow = DirectCast(lb.NamingContainer, GridViewRow)
lb.Text = DataBinder.Eval(container.DataItem, columnBinding).ToString
ElseIf sender.GetType = GetType(TextBox) Then
Dim tb As TextBox = DirectCast(sender, TextBox)
Dim container As GridViewRow = DirectCast(tb.NamingContainer, GridViewRow)
tb.Text = DataBinder.Eval(container.DataItem, columnBinding).ToString
ElseIf sender.GetType = GetType(CheckBox) Then
Dim cb As CheckBox = DirectCast(sender, CheckBox)
Dim container As GridViewRow = DirectCast(cb.NamingContainer, GridViewRow)
cb.Checked = DataBinder.Eval(container.DataItem, columnBinding).ToString
ElseIf sender.GetType = GetType(DropDownList) Then
Dim ddl As DropDownList = DirectCast(sender, DropDownList)
Dim container As GridViewRow = DirectCast(ddl.NamingContainer, GridViewRow)
If columnBinding = "criticalityRating" Then
ddl.Items.Add("")
For i = 1 To 4
ddl.Items.Add(i)
Next
ElseIf columnBinding = "property_id" Then
For Each p As PropertyMP In PropertyMPDB.GetProperties
ddl.Items.Add(New ListItem(p.propertyMP, p.property_id))
Next
End If
If templateType = DataControlRowType.DataRow Then
ddl.SelectedValue = DataBinder.Eval(container.DataItem, columnBinding).ToString
End If
End If
End Sub
End Class
DropDownList 绑定到它们自己的 ObjectDataSource 并在标记中创建。
据我了解,必须在 Page.Init 中的每次回发时实例化 GridView。Page.Load 创建网格视图为时已晚,因为它不会维护 ViewState 并且无法更新。但是,当我在 Init 上创建它时,还没有创建 DropDownLists 或 DataBound,因此没有选定的值。我尝试在它们的 Inits 上填充 DropDownLists,而不是将它们绑定到 DataSource,但是当我更改 SelectedValue 时它会引发 ViewState 错误。
当我在加载时创建 GridView 时,一切正常,除了最重要的部分,更新......
谁能帮我弄清楚在哪里初始化/绑定 GridView/DropDownLists?我已经为此苦苦挣扎了三天,在这里变得绝望:(