为了解决这个问题,我使用 Reflector 来确认 Repeater 在处理自己添加行时所做的工作,创建了一个继承自 Repeater 的 ExtensibleRepeater 并允许为每次更新添加一行。唯一的问题是您不能使用页脚概念,因为在页脚更新时会在页脚之后显示添加的行。
通过将相关的RepeaterItem 的Visible 设置为False 来处理删除行。
IIRC 你在回调中丢失数据的原因是因为你在回调时调用DataBind,这会重置所有现有数据,包括用户表单数据。
代码是专有的,但由于它基于 Reflector 对 .NET 2.0 Repeater 的显示,我可以向您展示一个经过编辑的版本:
Imports System.ComponentModel
Imports System.Security.Permissions
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
'''======================================================================
''' Class: ExtensibleRepeater
'''
''' <summary>
''' A <see cref="Repeater" /> that can be extended by one item.
''' </summary>
'''
''' <remarks>
''' BUG: If the <see cref="ExtensibleRepeater.FooterTemplate" /> is defined, the additional
''' item will appear after it!
''' </remarks>
'''
''' <revisionhistory>
''' 100907 MEH Created based upon reflection on Repeater.
''' </revisionhistory>
'''======================================================================
<snip>
Public Class ExtensibleRepeater
Inherits Repeater
Private additionalItem As RepeaterItem
<snip>
'''---------------------------------------------------------------------
''' Function: AddNew
'''
''' <summary>
''' Adds another <see cref="RepeaterItem"></see> to the <see cref="ExtensibleRepeater"></see>.
''' </summary>
'''
''' <param name="ItemData">
''' The data item to associate with the <see cref="RepeaterItem"></see>.
''' Ignored if <paramref name="UseDataSource"></paramref> is False.
''' </param>
''' <param name="UseDataSource">
''' Indicates whether to use the specified data source.
''' </param>
'''
''' <returns>The new <see cref="System.Web.UI.WebControls.RepeaterItem"></see>.</returns>
'''
''' <exception cref="NotSupportedException">Called more than once.</exception>
'''
''' <remarks>
''' Currently can only be called once. Must be called again after
''' <see cref="DataBind"></see> is called to recreate the additional item.
''' </remarks>
'''
''' <revisionhistory>
''' 100907 MEH Created based upon reflection on the protected Repeater.CreateControlHierarchy.
''' </revisionhistory>
'''---------------------------------------------------------------------
Public Function AddNew(ByVal ItemData As Object, Optional ByVal UseDataSource As Boolean = True) As RepeaterItem
<snip>
If additionalItem IsNot Nothing Then _
Throw New NotSupportedException
<snip>
additionalItem = CreateItem(dataItemCount, itemType, UseDataSource, ItemData)
<snip>
Return additionalItem
End Function
'''---------------------------------------------------------------------
''' Property: Items
'''
''' <summary>
''' Gets a collection of <see cref="System.Web.UI.WebControls.RepeaterItem"></see>
''' objects in the <see cref="ExtensibleRepeater"></see>.
''' </summary>
'''
''' <returns>
''' A collection of <see cref="System.Web.UI.WebControls.RepeaterItem"></see>
''' objects. The default is an empty <see cref="System.Web.UI.WebControls.RepeaterItemCollection"></see>.
''' </returns>
'''
''' <remarks></remarks>
'''
''' <revisionhistory>
''' 100907 MEH Created.
''' </revisionhistory>
'''---------------------------------------------------------------------
<snip>
Public Overrides ReadOnly Property Items() As RepeaterItemCollection
Get
If additionalItem IsNot Nothing Then
Dim newItems As New ArrayList(MyBase.Items)
newItems.Add(additionalItem)
Return New RepeaterItemCollection(newItems)
End If
Return MyBase.Items
End Get
End Property
'''---------------------------------------------------------------------
''' Function: CreateItem
'''
''' <summary>
''' Creates a <see cref="System.Web.UI.WebControls.RepeaterItem"></see>
''' with the specified item type and location within the <see cref="ExtensibleRepeater"></see>.
''' </summary>
'''
''' <param name="ItemIndex">
''' The specified location within the <see cref="ExtensibleRepeater"></see>
''' to place the created item.
''' </param>
''' <param name="ItemType">
''' A <see cref="System.Web.UI.WebControls.ListItemType"></see> that
''' represents the specified type of the <see cref="T:System.Web.UI.WebControls.Repeater"></see>
''' item to create.
''' </param>
''' <param name="DataBind">
''' Indicates whether to use the specified data source.
''' </param>
''' <param name="DataItem">
''' The data item to associate with the <see cref="RepeaterItem"></see>.
''' Ignored if <paramref name="DataBind"></paramref> is False.
''' </param>
'''
''' <returns>The new <see cref="System.Web.UI.WebControls.RepeaterItem"></see>.</returns>
'''
''' <remarks></remarks>
'''
''' <revisionhistory>
''' 100907 MEH Created from reflection on the private Repeater.CreateItem, with no changes.
''' </revisionhistory>
'''---------------------------------------------------------------------
Private Overloads Function CreateItem(ByVal ItemIndex As Integer, ByVal ItemType As ListItemType, ByVal DataBind As Boolean, ByVal DataItem As Object) As RepeaterItem
<snip>
'''---------------------------------------------------------------------
''' Property: FooterTemplate
'''
''' <summary>
''' Gets or sets the <see cref="System.Web.UI.ITemplate" /> that
''' defines how the footer section of the <see cref="ExtensibleRepeater" />
''' control is displayed.
''' </summary>
'''
''' <value>
''' A <see cref="System.Web.UI.ITemplate" /> that defines how the
''' footer section of the <see cref="ExtensibleRepeater" /> control is
''' displayed.
''' The default value is Nothing.
''' </value>
'''
''' <remarks>
''' This property does not change the inherited behaviour. It is
''' only overridden to highlight this missing feature:
''' TODO: BUG: This will appear before an additional item if one is added.
''' </remarks>
'''
''' <revisionhistory>
''' 100907 MEH Created.
''' </revisionhistory>
'''---------------------------------------------------------------------
<Obsolete("BUG: This will appear before an additional item if one is added.")> _
<Description("The template used for the footer. BUG: This will appear before an additional item if one is added."), _
Browsable(False), DefaultValue(CStr(Nothing)), _
PersistenceMode(PersistenceMode.InnerProperty), _
TemplateContainer(GetType(RepeaterItem))> _
Public Overrides Property FooterTemplate() As ITemplate
<snip>
'''---------------------------------------------------------------------
''' Sub: DataBind
'''
''' <summary>
''' Binds the <see cref="ExtensibleRepeater"></see> control and all
''' its child controls to the specified data source.
''' </summary>
'''
''' <remarks>
''' <see cref="AddNew"></see> must be called again to restore the
''' additional item if it is needed.
''' </remarks>
'''
''' <revisionhistory>
''' 100908 MEH Created.
''' </revisionhistory>
'''---------------------------------------------------------------------
Overrides Sub DataBind()
additionalItem = Nothing
<snip>
End Class