ASP.NET - Using CheckBoxes in a Repeater
I'm a tad confused. I have a Repeater which populates a list of Checkbox controls and Label controls. But it doesn't seem like the checked state of the checkboxes is remembered in ViewState until AFTER the first postback.
Scenario: I have 5 items in my custom checkbox list. I select the first 3 and submit the form. The first 3 are no longer selected. I select items 1, 3 and 5 and submit again. After the page is loaded 1, 3 and 5 are still selected.
Here's the entire code for the test page I'm using. My apologies for the VB :-p
Imports System.Xml
Partial Public Class _Default
Inherits System.Web.UI.Page
Dim _roles As Repeater
Dim _output As Literal
Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
_roles = New Repeater()
_roles.ItemTemplate = New RolesListTemplate(ListItemType.Item)
Me.Form.Controls.Add(_roles)
Dim btn As New Button()
btn.Text = "Save"
btn.UseSubmitBehavior = True
AddHandler btn.Command, AddressOf btnSave_OnCommand
Me.Form.Controls.Add(btn)
_output = New Literal
Me.Form.Controls.Add(_output)
End Sub
Private Sub btnSave_OnCommand(ByVal sender As Object, ByVal e As CommandEventArgs)
Dim roleData As String = GetXML(_roles)
_output.Text = "<br>" & HttpUtility.HtmlEncode(roleData) & "<br>DONE"
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
Dim RoleData As New List(Of Role)
RoleData.Add(New Role With {.selected = 0, .enabled_ind = 1, .role_id = 123, .role_description = "Role 123"})
RoleData.Add(New Role With {.selected = 0, .enabled_ind = 1, .role_id = 345, .role_description = "Role 345"})
RoleData.Add(New Role With {.selected = 0, .enabled_ind = 1, .role_id = 678, .role_description = "Role 678"})
RoleData.Add(New Role With {.selected = 0, .enabled_ind = 1, .role_id = 6987, .role_description = "Role 6987"})
RoleData.Add(New Role With {.selected = 0, .enabled_ind = 1, .role_id = 1122, .role_description = "Role 1122"})
If RoleData IsNot Nothing Then
If RoleData.Count > 0 Then
_roles.DataSource = RoleData
_roles.DataBind()
_roles.Visible = True
Else
_roles.Visible = False
End If
End If
End If
End Sub
Private Function GetXML(ByVal _cb_roles As Repeater) As String
Dim settings As New XmlWriterSettings
settings.CheckCharacters = True
settings.CloseOutput = True
settings.OmitXmlDeclaration = True
Dim xw As XmlWriter
Dim sb As New StringBuilder()
xw = XmlWriter.Create(sb, settings)
xw.WriteStartDocument()
xw.WriteStartElement("roles")
For Each row As RepeaterItem In _cb_roles.Items
Dim pnl As Panel = TryCast(row.Controls.Item(0), Panel)
Dim cb As CheckBox = TryCast(pnl.Controls.Item(0), CheckBox)
Dim id As String = String.Empty
Dim parts() As String = cb.ID.Split("_"c)
id = cb.InputAttributes("role_id")
xw.WriteStartElement("role")
xw.WriteAttributeString("role_id", id)
If cb.Checked Then
xw.WriteAttributeString("selected", "1")
Else
xw.WriteAttributeString("selected", "0")
End If
xw.WriteEndElement()
Next
xw.WriteEndElement()
xw.WriteEndDocument()
xw.Close()
Return sb.ToString
End Function
Public Class RolesListTemplate
Implements ITemplate, INamingContainer
Private _ltItemType As ListItemType
Private _ctlParent As WebControl
Sub New(ByVal pType As ListItemType)
Try
_ltItemType = pType
Catch ex As Exception
Throw ex
End Try
End Sub
Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) Implements System.Web.UI.ITemplate.InstantiateIn
Select Case _ltItemType
Case ListItemType.Header
Case ListItemType.Item
Dim pnl As New Panel()
Dim cb As New CheckBox()
cb.AutoPostBack = True
cb.ID = "role_check"
AddHandler cb.DataBinding, AddressOf RolesListTemplate_DataBind
pnl.Controls.Add(cb)
Dim lbl As New Label()
lbl.ID = "role_lbl"
AddHandler lbl.DataBinding, AddressOf RolesListTemplate_DataBind
pnl.Controls.Add(lbl)
container.Controls.Add(pnl)
Case ListItemType.AlternatingItem
Case ListItemType.Footer
End Select
End Sub
Private Sub RolesListTemplate_DataBind(ByVal sender As Object, ByVal e As System.EventArgs)
Dim _sender As Control = DirectCast(sender, Control)
Dim container As RepeaterItem = DirectCast(_sender.NamingContai开发者_JAVA技巧ner, RepeaterItem)
Dim role As Role = TryCast(container.DataItem, Role)
If role IsNot Nothing Then
If role.selected OrElse role.enabled_ind Then
Select Case _sender.ID
Case "role_check"
Dim role_check As CheckBox = DirectCast(_sender, CheckBox)
role_check.Checked = role.selected
role_check.ID = "role_list_" & role.role_id.ToString()
role_check.InputAttributes("role_id") = role.role_id.ToString()
Case "role_lbl"
Dim role_lbl As Label = DirectCast(_sender, Label)
role_lbl.Text = role.role_description
End Select
Else
container.Visible = False
End If
End If
End Sub
End Class
Public Class Role
Public enabled_ind As Boolean
Public selected As Boolean
Public role_id As Integer
Public role_description As String
End Class
End Class
This is a very common mistake. You want to call DataBind
in the Init
event, even for post backs.
精彩评论