带有TemplateField的Ddynamic GridView - LifeCycle中的混淆 [英] Ddynamic GridView with TemplateFields - confusion in LifeCycle
问题描述
我有一个动态创建的databound gridview。数据源基于几个DropDownLists返回一个对象(对象类型不同)。根据对象的类型,GridView必须显示特定于特定对象的字段。另外,还有一个DropDownList,它的SelectedValue决定一个对象的哪些列将被添加/排除在GridView上。
这是一个创建GridView的方法(我写入VB.NET,但C#也是非常受欢迎的):
pre $ Private $ CreateGridView(
Dim gv As New GridView
使用gv
.AllowSorting = True
.AutoGenerateColumns = False
.CssClass =gv
.EmptyDataText =列表为空
.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
如果ddlStages.SelectedValue<> 然后
如果ddlStages.SelectedValue> = item.stage_id然后
Dim tf As New TemplateField()
tf.SortExpression = item.col
tf.HeaderTemplate = New GridViewTemplate (item.title,item.col)
tf.ItemTemplate =新的GridViewTemplate(DataControlRowType.DataRow,item.col,item.ctrlType,item.length)
tf.FooterTemplate =新的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
公共类GridViewTemplate
Implements ITemplate
私有templateType作为DataControlRowType
私有标题作为字符串
私有columnBinding作为字符串
私有ctrlType作为字符串
私有长度作为整数
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)实现ITemplate.InstantiateIn
Select Case temp lateType
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)
退出选择
Case DataControlRowType.DataRow
如果ctrlType = LabelThen
Dim lbl = New Label()
lbl.ID =lbl+ columnBinding
AddControl(lbl,container)
ElseIf ctrlType =TextBoxThen
Dim tb As New TextBox
tb.ID =tb+ columnBinding
tb.MaxLength = length
AddControl(tb,container)
ElseIf ctrlType =CheckBoxThen
Dim cb =新的CheckBox()
cb.ID =cb+ columnBinding
AddControl(cb,container)
ElseIf ctrlType =DropDownListThen
Dim ddl = New DropDownList()
ddl.ID = ddl+ columnBinding
AddControl(ddl,container)
结束如果
退出选择
Case DataControlRowType.Footer
如果ctrlType =LabelThen
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 =TextBoxThen
Dim tb As New TextBox
tb.ID =tb+ columnBinding
tb.MaxLength = length
container.Controls.Add(tb)
ElseIf ctrlType =CheckBoxThen
Dim cb = New CheckBox()
cb.ID =cb + columnBinding
container.Controls.Add(cb)
ElseIf ctrlType =DropDownListThen
Dim ddl = New DropDownList()
ddl.ID =ddl+ columnBinding
AddControl(ddl,container)
结束如果
退出选择
案例否
退出选择
结束选择
结束小组
Private Sub AddControl(ctrl作为控件,容器作为控件)
AddHandler ctrl.DataBinding,AddressOf OnDataBinding
container.Controls.Add(ctrl)
End Sub
Private Sub OnDataBinding(ByVal sender As Object,ByVal e As EventArgs)
如果sender.GetType = G etType(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)然后
Dim ddl As DropDownList = Dire ctCast(sender,DropDownList)
Dim container As GridViewRow = DirectCast(ddl.NamingContainer,GridViewRow)
如果columnBinding =criticalityRating则
ddl.Items.Add()
对于i = 1到4
ddl.Items.Add(i)
下一个
ElseIf columnBinding =property_idThen
对于每个p作为PropertyMP在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是为了创建gridview而迟到的,因为它不会维护ViewState并且不可能更新。但是,当我在Init上创建它时,DropDownLists尚未创建或DataBound,所以没有选定的值。我尝试在它们的Inits上填充DropDownLists,而不是将它们绑定到DataSource,但是当我更改SelectedValue时它抛出ViewState错误。
当我在Load上创建GridView时,一切正常,除了最重要的部分,更新...
任何人都可以帮我弄清楚我在哪里初始化/绑定GridView / DropDownLists?我一直在为此挣扎三天,在这里变得绝望:($ / b>
没有找到解决方案,但找到了解决方法。
GridView被创建为OnInit,字段被添加在GridView Init上。所有的DropDownLists都是DataBound后,ObjectDataSource从DropDownLists接收其参数。
有一个DropDownList,它负责返回的对象的类型,当我改变SelectedValue之后,DropDownList被重新启动并且ObjectDataSource仍然有旧的值并返回错误的对象。是错误发生的地方 - 绑定GridView和带有错误字段的对象,取而代之的是,我使用了QueryString并做了一个回发,在下一次加载时,ObjectDataSource返回匹配GridView字段的正确对象。 / p>
I have a databound gridview that I create dynamically. The datasource returns an object based on the several DropDownLists (types of objects are different). Depending on the type of the object, the GridView must display certain fields specific only for the object. Also, there is a DropDownList whose SelectedValue decides which columns of an object will be added/excluded from the GridView.
Here is a method that creates the GridView (I write in VB.NET but C# is also very welcome):
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
The GridView is always in Edit mode, meaning, it's ItemTemplate is a TexBox/DropDownList/CheckBox. Here is an ITemplate Class:
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
The DropDownLists are bound to their own ObjectDataSources and are created in the mark-up.
As I understand, the GridView must be instantiated on every postback in the Page.Init. The Page.Load is to late for creating the gridview as it will not maintain the ViewState and will be impossible to update. However, when I create it on Init, the DropDownLists are not created or DataBound yet, so there is no selected value. I tried populating the DropDownLists on their Inits instead of bining them to the DataSource but it throws a ViewState error when I change the SelectedValue.
When I create the GridView on Load, everything works perfectly, except the most important part, updating...
Can anyone help me with figuring out where do I initialize/bind the GridView/DropDownLists? I have been struggling with this for three days now, getting desperate here :(
Did not find a solution but found a workaround.
The GridView is created OnInit, fields are added on GridView Init. After all of the DropDownLists are DataBound, the ObjectDataSource receives its parameters from the DropDownLists.
There is one DropDownList, which is responsible for the type of Object returned. After I change the SelectedValue, the DropDownList is reinitiated and ObjectDataSource still has the old value and returns the wrong object. This is where the error was - binding GridView with an Object with wrong fields. Instead of this, I used QueryString and did a postback. On the next load, the ObjectDataSource returns the correct object that matches GridView's fields. Everything is smooth from there.
这篇关于带有TemplateField的Ddynamic GridView - LifeCycle中的混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!