1

動的に作成するデータバインドされたグリッドビューがあります。データソースは、いくつかの 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日間苦労しており、ここで必死になっています:(

4

1 に答える 1

1

解決策は見つかりませんでしたが、回避策が見つかりました。

GridView は OnInit で作成され、フィールドは GridView Init で追加されます。すべての DropDownLists が DataBound になった後、ObjectDataSource は DropDownLists からパラメーターを受け取ります。

返されるオブジェクトのタイプを担当する DropDownList が 1 つあります。SelectedValue を変更した後、DropDownList が再起動され、ObjectDataSource にはまだ古い値があり、間違ったオブジェクトが返されます。これがエラーの場所です-GridViewを間違ったフィールドを持つオブジェクトにバインドします。これの代わりに、QueryString を使用してポストバックを行いました。次回の読み込み時に、ObjectDataSource は GridView のフィールドに一致する正しいオブジェクトを返します。そこからすべてがスムーズです。

于 2013-04-11T23:05:00.167 に答える