如何访问在循环中动态生成的复选框

时间:2014-05-14 14:50:09

标签: asp.net vb.net checkbox

我是asp.net和vb.net编程的新手,我无法找到问题的答案。我在sub中的运行时循环中动态生成了复选框。

这是一个网格计划程序,可以显示从不同页面中选择的位置的选定日期和所选小时数。我想通过id访问复选框,但我无法访问它们,因为复选框未在类级别声明。

任何人都可以帮助我,我整天都在寻找解决方案。我更喜欢VB,但C#也没问题。

以下是我的代码隐藏

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    If Not IsPostBack Then
      BindLocationDayTime()
   End If
End Sub

Public Sub BindLocationDayTime()
        Dim ID As Integer
        Dim Name As String
        Dim Day As Integer
        Dim Time As Integer
        Dim StartDate As DateTime
        Dim EndDate As DateTime

        Dim Locations As SqlDataReader = GetLocations()

        For Each Item In Locations

            Dim LRow As New TableRow()
            Dim LCell As New TableCell()
            LCell.Text = Locations.Item("Name")
            LCell.Attributes.Add("class", "LocationHeader")
            LCell.Attributes.Add("colspan", "5")
            LRow.Cells.Add(LCell)
            LocationData.Rows.Add(LRow)

            Dim Location As SqlDataReader = GetLocation(Convert.ToInt32(Locations.Item("Id")))

            While Location.Read()
                Name = Location("Name").ToString()
                StartDate = Location("StartDate")
                EndDate = Location("EndDate")
            End While

            Dim dtfi As Globalization.DateTimeFormatInfo = Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat
            Dim tRowCount As Integer = 0

            Do While StartDate <= EndDate
                Dim LocationDayTime As SqlDataReader = GetPlayDayTime(Convert.ToInt32(Locations.Item("Id")))

                For Each row In LocationDayTime
                    Day = LocationDayTime.Item("DayID")
                    Time = LocationDayTime.Item("TimeID")
                    ID = Locations.Item("Id")
                    If Day = 1 Then
                        If StartDate.DayOfWeek = DayOfWeek.Monday Then
                            BindDays(StartDate, ID, tRowCount, Time)
                            tRowCount = tRowCount + 1
                        End If
                    ElseIf Day = 2 Then
                        If StartDate.DayOfWeek = DayOfWeek.Tuesday Then
                            BindDays(StartDate, ID, tRowCount, Time)
                            tRowCount = tRowCount + 1
                        End If
                    ElseIf Day = 3 Then
                        If StartDate.DayOfWeek = DayOfWeek.Wednesday Then
                            BindDays(StartDate, ID, tRowCount, Time)
                            tRowCount = tRowCount + 1
                        End If
                    ElseIf Day = 4 Then
                        If StartDate.DayOfWeek = DayOfWeek.Thursday Then
                            BindDays(StartDate, ID, tRowCount, Time)
                            tRowCount = tRowCount + 1
                        End If
                    ElseIf Day = 5 Then
                        If StartDate.DayOfWeek = DayOfWeek.Friday Then
                            BindDays(StartDate, ID, tRowCount, Time)
                            tRowCount = tRowCount + 1
                        End If
                    End If
                Next
                StartDate = StartDate.AddDays(1)
            Loop
        Next
    End Sub

Public Sub BindDays(ByVal StartDate As DateTime, ByVal ID As Integer, ByVal tRowCount As Integer, ByVal Time As Integer)
        Dim dtfi As Globalization.DateTimeFormatInfo = Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat
        Dim tRow As New TableRow()

        Dim Cell1 As New TableCell()
        Dim strDayOfWeek As String = dtfi.GetDayName(StartDate.DayOfWeek)
        Cell1.Text = UppercaseFirstLetter(strDayOfWeek & " ") & (StartDate.Date.ToShortDateString & " om ") & (Time & "uur ")
        Cell1.Attributes.Add("class", "MemberCell")
        tRow.Cells.Add(Cell1)

        Dim Cell2 As New TableCell()
        Dim cbAvailible As New CheckBox()
        cbAvailible.ID = (StartDate.Date) & "," & (Time)
        cbAvailible.Checked = False
        Cell2.Controls.Add(cbAvailible)
        tRow.Cells.Add(Cell2)

        Dim Cell3 As New TableCell()
        Dim Label As New Label()
        Label.Text = ("(Op deze datum ben ik verhinderd)")
        Cell3.Controls.Add(Label)
        tRow.Cells.Add(Cell3)

        If tRowCount Mod 2 Then
            tRow.Attributes.Add("class", "alternatingItemStyle")
        Else
            tRow.Attributes.Add("class", "itemStyle")
        End If

        LocationData.Rows.Add(tRow)

    End Sub

#End Region

#Region " Events "

Private Sub Insert_Click(sender As Object, e As EventArgs) Handles Insert.Click
' I want to get here al the checkbox id and insert the values to a databse
End Sub

End Region

2 个答案:

答案 0 :(得分:0)

' Global declaration inside the "Form" class.
Public Checkboxes as New List(of Checkbox)

每次创建“新复选框”时,都会将其添加到集合中。

...
Dim cbAvailible As New CheckBox()
Checkboxes.Add(cbAvailable)
...

稍后您可以简单地参阅索引复选框。

Dim chk as boolean = Checkboxes(2).checked ' example

另一个选择是使用Generic.Dictionary来存储复选框,在这种情况下,每个框都可以有一个“Key”,就像一个与行或特定内容相关的字符串。

通过复选框循环。

For iQ AS integer = 0 to Checkboxes.Count -1
    Dim cb as checkbox = Checkboxes(iq) ' just a way to not use long name during operations.
    Dim checked as boolean = cb.checked ' ... ' do your work here
    ' ...
Next iQ

您可能需要对所有对象(每行)执行相同的操作。

最后一个索引对于所有这些索引应该是相同的。这也应该与表对象中的行数相同。

答案 1 :(得分:0)

解决方案1 ​​ - 使用递归控制搜索

我使用动态生成的表单做了类似的事情,其中​​包含可变数量的控件(文本框,下拉列表和复选框),控件状态是数据驱动的。我不希望绑定生成的控件的事件(需要一个生涩的回发),但有一个“保存”按钮,并从该事件做一个递归的GetChildControls函数,从持有动态控件的容器开始。为每个动态控件分配一个id时有一个约定,所以当你以后循环回来时,你可以知道哪个控件与哪个记录有关。

递归函数:

Public Class ControlUtils
    Shared Function GetChildControls(ByVal ctrl As Control, Optional ByVal ctrlType As Type = Nothing) As Control()
        Dim controls As New ArrayList()
        For Each c As Control In ctrl.Controls
            ' add this control and all its nested controls
            If ctrlType Is Nothing OrElse ctrlType.IsAssignableFrom(c.GetType()) Then
                controls.Add(c)
                controls.AddRange(GetChildControls(c))
            End If
        Next
        ' return the result as an array of Controls
        Return DirectCast(controls.ToArray(GetType(Control)), Control())
    End Function
End Class

具有人为的动态形式的基本理念......

表示数据库信息的类:

Public Class Location
    Public Property ID As Integer
    Public Property Name As String
    Public Property StartDate As Date
    Public Property EndDate As Date

    Shared Function GetSampleLocations() As List(Of Location)
        Dim sample As New List(Of Location)
        Dim loc As Location
        For j = 1 To 5
            loc = New Location
            loc.ID = j
            loc.Name = "Location " & j
            loc.StartDate = Date.Today
            loc.EndDate = Date.Today.AddDays(6 - j)
            sample.Add(loc)
        Next
        Return sample
    End Function
End Class

具有构建“表单”并保存其数据的方法的类:

Public Class LocationsDynamicForm

    Dim _Locations As IEnumerable(Of Location)

    Sub New(locations As IEnumerable(Of Location))
        _Locations = locations
    End Sub

    Sub InsertEditForm(plc As PlaceHolder, setUserInput As Boolean)
        'build and add controls to placeholder
        Dim tbl As New Table
        Dim r As TableRow
        Dim c As TableCell
        For Each loc As Location In _Locations
            r = New TableRow

            'add cell for location name
            c = New TableCell
            c.Controls.Add(New LiteralControl(loc.Name)) 'add plain text through literal control
            r.Cells.Add(c)

            'add cell for each day in the date range for current location
            Dim currentDate As Date = loc.StartDate
            Do Until currentDate > loc.EndDate
                c = New TableCell
                Dim chk As New CheckBox
                chk.ID = "chkLocationDate_" & loc.ID & "_" & currentDate.Ticks
                chk.Text = currentDate.ToShortDateString
                If setUserInput Then
                    'set the check state based on current database value
                    Dim pretendValueCameFromDB As Boolean = True
                    chk.Checked = pretendValueCameFromDB
                End If
                c.Controls.Add(chk)
                r.Cells.Add(c)
                currentDate = currentDate.AddDays(1)
            Loop

            tbl.Rows.Add(r)
        Next
        plc.Controls.Add(tbl)
    End Sub

    Sub SaveForm(ByVal plc As PlaceHolder)
        Dim ctl As Control
        Dim controlIDParts() As String
        Dim drp As DropDownList
        Dim txt As TextBox
        Dim chk As CheckBox
        For Each ctl In ControlUtils.GetChildControls(plc, GetType(Control))
            If ctl.GetType Is GetType(DropDownList) Then
                drp = CType(ctl, DropDownList)
                If drp.ID Like "drpIT_*" Then
                    controlIDParts = drp.ID.Split("_")
                    'update record...
                End If
            ElseIf ctl.GetType Is GetType(TextBox) Then
                txt = CType(ctl, TextBox)
                If txt.ID Like "txtIT_*" Then
                    controlIDParts = txt.ID.Split("_")
                    'update record...
                End If
            ElseIf ctl.GetType Is GetType(CheckBox) Then
                chk = CType(ctl, CheckBox)
                If chk.ID Like "chkLocationDate_*" Then
                    controlIDParts = chk.ID.Split("_")
                    Dim locationID = controlIDParts(1)
                    Dim ticks As Long = Val(controlIDParts(2))
                    Dim d As New Date(ticks)
                    'update record...
                End If
            End If
        Next
        'commit record changes...
    End Sub

End Class

它在webform中的使用(假设你有一个保存按钮和占位符控件):

Dim _Locations As List(Of Location)
Dim _LocationsForm As LocationsDynamicForm

Protected Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init
    _Locations = Location.GetSampleLocations()
    _LocationsForm = New LocationsDynamicForm(_Locations)
    _LocationsForm.InsertEditForm(plcLocations, Not Me.IsPostBack)
End Sub

Protected Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
    _LocationsForm.SaveForm(plcLocations)
End Sub

解决方案2 - 将AddHandler与动态添加的控件一起使用

这更接近您的需求,但每次复选框更改都需要回发。在BindDays例程中,在添加复选框时添加这些行。

cbAvailible.AutoPostBack = True
AddHandler cbAvailible.CheckedChanged, AddressOf Insert_Click

您应该修剪子Insert_Click签名末尾的Handles关键字。当您预先知道您将要处理的控件但在设计时控件不存在时,Handles很好。

Private Sub Insert_Click(sender As Object, e As EventArgs)
    ' I want to get here al the checkbox id and insert the values to a databse
    Dim chk As CheckBox = CType(sender, CheckBox)
    Label1.Text = "ID = " & chk.ID & ", Checked = " & chk.Checked
End Sub

我不确定你是如何在回发中持久保存'LocationData'或将其添加到网页中的,但我能够获得修改后的代码版本。