1

我有一个动态创建的数据绑定网格视图。数据源根据几个 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?我已经为此苦苦挣扎了三天,在这里变得绝望:(

4

1 回答 1

1

没有找到解决方案,但找到了解决方法。

GridView 在 OnInit 上创建,在 GridView Init 上添加字段。在所有的 DropDownLists 都是 DataBound 之后,ObjectDataSource 从 DropDownLists 接收它的参数。

有一个 DropDownList,负责返回 Object 的类型。更改 SelectedValue 后,DropDownList 重新启动,ObjectDataSource 仍然具有旧值并返回错误的对象。这就是错误所在 - 将 GridView 与具有错误字段的对象绑定。取而代之的是,我使用了 QueryString 并进行了回发。在下一次加载时,ObjectDataSource 返回与 GridView 的字段匹配的正确对象。从那里一切都很顺利。

于 2013-04-11T23:05:00.167 回答