動的に作成するデータバインドされたグリッドビューがあります。データソースは、いくつかの DropDownLists に基づいてオブジェクトを返します (オブジェクトのタイプは異なります)。オブジェクトの種類に応じて、GridView はオブジェクト専用の特定のフィールドを表示する必要があります。また、オブジェクトのどの列を GridView に追加/除外するかを決定する SelectedValue を持つ DropDownList もあります。
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
DropDownLists は、独自の ObjectDataSources にバインドされ、マークアップで作成されます。
私が理解しているように、GridView は Page.Init のすべてのポストバックでインスタンス化する必要があります。Page.Load は、ViewState を維持せず、更新できないため、グリッドビューを作成するには遅すぎます。ただし、Initで作成すると、DropDownListsは作成されていないか、DataBoundがまだ作成されていないため、選択された値はありません。DropDownLists を DataSource にバインドするのではなく、Inits に入力しようとしましたが、SelectedValue を変更すると ViewState エラーがスローされます。
ロード時に GridView を作成すると、最も重要な部分である更新を除いて、すべてが完全に機能します...
GridView/DropDownListsをどこで初期化/バインドするかを理解するのを手伝ってくれる人はいますか? 私はこれに3日間苦労しており、ここで必死になっています:(