1

I have a DataList inside a DataList that causes my page to lose the controls. The page works and there are no errors, but my label is never found! This is odd because the label shows on the aspx page, it just doesn't remove the 2 items that I want it to remove. When debugging, it skips over the If statement altogether:

If lbl IsNot Nothing Then
    If lbl.Text = "Self Directed" Or lbl.Text = "Systems" Then
        lbl.Visible = False
    End If
End If

I don't understand why it thinks the Label is Null because it is pulling information from the database and there are no null values.

Protected Sub DataList1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataListItemEventArgs) Handles DataList1.ItemDataBound
    If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
        'Find the controls that are inside the DataList
        Dim anstype As HiddenField = e.Item.FindControl("HiddenField1")
        Dim questionid As HiddenField = e.Item.FindControl("HiddenField2")
        Dim rbl As RadioButtonList = e.Item.FindControl("RadioButtonList1")
        Dim cbl As CheckBoxList = e.Item.FindControl("CheckBoxList1")
        Dim txt As TextBox = e.Item.FindControl("TextBox1")
        Dim ds As DataSet = GetDataSet(questionid.Value)
        Select Case anstype.Value
            'if anstype is 's' then show a radio button list
            Case "S"
                rbl.Visible = True
                cbl.Visible = False
                txt.Visible = False
                rbl.DataSource = ds
                rbl.DataTextField = "Choice"
                rbl.DataValueField = "ChoiceID"
                rbl.DataBind()
                'if anstype is 'm' then show a checkbox list
            Case "M"
                rbl.Visible = False
                cbl.Visible = True
                txt.Visible = False
                cbl.DataSource = ds
                cbl.DataTextField = "Choice"
                cbl.DataValueField = "ChoiceID"
                cbl.DataBind()
                'if anstype is 't' then show a textbox
            Case "T"
                rbl.Visible = False
                cbl.Visible = False
                txt.Visible = True
        End Select
        Dim dl2 As DataList = CType(e.Item.FindControl("DataList2"), DataList)
        Dim hidden2 As HiddenField = DirectCast(e.Item.FindControl("HiddenField2"), HiddenField)
        Dim QID As Integer = Int32.Parse(hidden2.Value)
        If QID = 33 Then
            For Each li As DataListItem In dl2.Items
                Dim lbl As Label = DirectCast(e.Item.FindControl("Label3"), Label)
                If lbl IsNot Nothing Then
                    If lbl.Text = "Self Directed" Or lbl.Text = "Systems" Then
                        lbl.Visible = False
                    End If
                End If
            Next
        End If
    End If
End Sub


<asp:DataList ID="DataList1" runat="server" DataSourceID="SqlDataSource1" Width="100%" CellPadding="4" ForeColor="#333333">
<ItemTemplate>

<asp:HiddenField ID="HiddenField2" runat="server" Value='<%# Eval("QuestionID") %>'>
</asp:HiddenField>
<asp:Label ID="lblQuesNum" runat="server" Font-Bold="True" Text='<%# Eval("QuestionNum") %>'>
</asp:Label>
<strong>)</strong>
<asp:Label ID="Label2" runat="server" Font-Bold="True" Text='<%# Eval("Question") %>'>
</asp:Label>
<asp:HiddenField ID="hiddenPicklistID" runat="server"  Value='<%# Eval("PicklistID") %>'>
</asp:HiddenField>
<asp:HiddenField ID="HiddenField1" runat="server" Value='<%# Eval("AnswerType") %>'>  
</asp:HiddenField>

<asp:DataList ID="DataList2" runat="server" DataSourceID="dsPicklist">
<ItemTemplate>
    <asp:HiddenField ID="hidPickID" runat="server" value='<%# Eval("PICKLISTID") %>'>  
    </asp:HiddenField>
    <asp:Label ID="Label3" runat="server" Text='<%# Eval("TEXT") %>'></asp:Label> 
</ItemTemplate>
</asp:DataList>

</asp:DataList>

UPDATE: I changed the code somewhat, but now I get the error Object reference not set to an instance of an object. on Line 47

Line 45:             Dim dl2 As DataList = CType(e.Item.FindControl("DataList2"), DataList)
Line 46:             Dim hidden2 As HiddenField = DirectCast(e.Item.FindControl("HiddenField2"), HiddenField)
Line 47:             Dim QID As Integer = Int32.Parse(hidden2.Value)
Line 48:             If QID = 33 Then
Line 49:                 For Each li As DataListItem In dl2.Items



Protected Sub DataList1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataListItemEventArgs) Handles DataList1.ItemDataBound
    If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
        'Find the controls that are inside the DataList
        Dim anstype As HiddenField = e.Item.FindControl("HiddenField1")
        Dim questionid As HiddenField = e.Item.FindControl("HiddenField2")
        Dim rbl As RadioButtonList = e.Item.FindControl("RadioButtonList1")
        Dim cbl As CheckBoxList = e.Item.FindControl("CheckBoxList1")
        Dim txt As TextBox = e.Item.FindControl("TextBox1")
        Dim ds As DataSet = GetDataSet(questionid.Value)
        Dim dl2 As DataList = e.Item.FindControl("DataList2")
        dl2.DataBind()
        Select Case anstype.Value
..... the rest of this code is the same as above until Case "T"....


Protected Sub DataList2_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataListItemEventArgs)
    If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
        Dim dl2 As DataList = CType(e.Item.FindControl("DataList2"), DataList)
        Dim hidden2 As HiddenField = DirectCast(e.Item.FindControl("HiddenField2"), HiddenField)
        Dim QID As Integer = Int32.Parse(hidden2.Value)
        If QID = 33 Then
            For Each li As DataListItem In dl2.Items
                Dim lbl As Label = DirectCast(e.Item.FindControl("Label3"), Label)
                If lbl IsNot Nothing Then
                    If lbl.Text = "Self Directed" Or lbl.Text = "Systems" Then
                        lbl.Visible = False
                    End If
                End If
            Next
        End If
    End If
End Sub

<asp:DataList ID="DataList2" runat="server" DataSourceID="dsPicklist" OnItemDataBound="DataList2_ItemDataBound">
<ItemTemplate>
    <asp:HiddenField ID="hidPickID" runat="server" value='<%# Eval("PICKLISTID") %>'></asp:HiddenField>
    <asp:Label ID="Label3" runat="server" Text='<%# Eval("TEXT") %>'></asp:Label> 
</ItemTemplate>
</asp:DataList>

UPDATE: Working code post!

Protected Sub DataList2_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataListItemEventArgs)
    If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
        Dim DataList2 = DirectCast(sender, DataList)
        Dim ParentItem = DirectCast(DataList2.NamingContainer, DataListItem)
        Dim HiddenField2 = DirectCast(ParentItem.FindControl("HiddenField2"), HiddenField)
        Dim QID As Integer = Int32.Parse(HiddenField2.Value)
        If QID = 33 Then
            For Each li As DataListItem In DataList2.Items
                Dim lbl As Label = DirectCast(e.Item.FindControl("Label3"), Label)
                If lbl IsNot Nothing Then
                    If lbl.Text = "Self Directed" Or lbl.Text = "Systems" Then
                        lbl.Visible = False
                    End If
                End If
            Next
        End If
    End If
End Sub

This will only hide the text for "Systems", I have gone through each label in that particular question and each has hidden itself. This code does work on another page so I know that Self Directed is exactly how it is capitalized. I even copied and pasted from the database and it still wouldn't hide. Very stubborn.

Jamie
  • 1,579
  • 8
  • 34
  • 74

2 Answers2

5

This should work:

Dim lbl As Label = DirectCast(li.FindControl("Label3"), Label)

Since the Label is in the inner DataList item that you're looping.

By the way, the same applies to you HiddenField hidPickID if that would be your next error ;-)

Edit;

I would recommend to handle the DataList2.ItemDataBound event as well. Then your code is less error-prone and clearer and you don't need to loop all items in DataList1.ItemDataBound.

You need to call DataList2.DataBind before in DataList1.ItemDataBound.

Edit2:

You can cast DataList2.NamingContainer to DataListItem to get the parent-item, then you can find your HiddenField(in DateList2.ItemDataBound):

Dim DataList2 = DirectCast(sender, DataList)
Dim ParentItem = DirectCast(DataList2.NamingContainer), DataListItem)
Dim HiddenField2 = DirectCast(ParentItem.FindControl("HiddenField2"),HiddenField)

But i would recommend to use the DataSource instead, for example(in DateList2.ItemDataBound):

Dim rowView As DataRowView = CType(e.Item.DataItem, DataRowView)
Dim QID = DirectCast(rowView("QID"), Int32)

(if it's stored in the DataRow what it should)

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • I changed it and now it goes through the If statement. It still doesn't hide those 2 label items though. And I have tried handling the DataList2 ItemDataBound before but it never even hits it. That is why I threw that code in with the DataList1.....it will run through it that way. – Jamie Feb 14 '12 at 16:48
  • 1
    @jlg: Then you missed to call DataList2.DataBind in DataList1.ItemDataBound(see my edit). Even if your code would work now, i still recommend to use DataList2.ItemDataBound to separate both from each other. You can still get the reference to the DataList1-Item there. – Tim Schmelter Feb 14 '12 at 17:16
  • I put `Dim dl2 As DataList = DataList1.FindControl("DataList2") dl2.DataBind()` before the line `If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then` and I get the error `Object reference not set to an instance of an object.` I put that same 2 lines right underneath the If e.Item line and the DataList2_ItemDataBound still doesn't get run. Do you know why it won't find anything on my page? – Jamie Feb 14 '12 at 19:29
  • You need to ensure that your current item is a `ListItemType.Item` or `ListItemType.AlternatingItem`. Have you really added the `ItemdataBound` handler to DataList2(on aspx or in codebehind)? Try to set the DataSource as well before you bind it. What is `dsPicklist`? – Tim Schmelter Feb 14 '12 at 19:36
  • `dsPicklist` is the `SqlDataSource` for `DataList2` – Jamie Feb 14 '12 at 20:07
  • I edited the original post with the way the code behind looks now. – Jamie Feb 14 '12 at 20:54
  • @jlg: As i've already said, of course you need to check **first** if the item's ÌtemType` is `ListItemType.Item`before you can find the nested DataList. – Tim Schmelter Feb 14 '12 at 21:14
  • @jlg: ... and not via `DataList1.FindControl("DataList2")` but `e.Item.FindControl(...)`. In `DataList2_ItemDataBound` this is redundant and wrong since you are already handling `DataList2.ItemDataBound`. So you can cast the sender to your DataList if you need a reference. `Dim DataList2=DirectCast(sender,DataList)`. But you don't need it there to get your controls. e.Item.FindControl is again the correct way: `Dim lbl As Label = DirectCast(e.Item.FindControl("Label3"), Label)` – Tim Schmelter Feb 14 '12 at 21:22
  • 1
    @jlg: ... and last but not least: i don't see that you add an handler for this event on DataList2. Add this to your aspx: `` – Tim Schmelter Feb 14 '12 at 21:45
  • Ok I added the `OnItemDataBound` to the `DataList` control and it doesn't skip over the ItemDataBound in the code behind now. Except now it can't find `HiddenField2` since that is located in the first `DataList`. – Jamie Feb 14 '12 at 22:18
  • @jlg: I've edited my answer again to show you two ways to get your hiddenfield value, what actually is the question-ID and should be stored in the DataSource of DataList2. The second way makes your HiddenField approach redundant. – Tim Schmelter Feb 14 '12 at 22:37
  • @jlg: Not ListViewItem, i meant DataListItem. Corrected my answer. – Tim Schmelter Feb 14 '12 at 22:46
  • Thanks so much for all your help! I am able to hide one of the items that is in that second `DataList`. For some reason it won't hide "Self Directed", I have gone through and hidden the other 3 labels individually, but that one just won't hide. Hah – Jamie Feb 15 '12 at 15:54
  • @jlg: You're welcome! I wouldn't use the text to detect whether it should be visible or not(you might change it later,consider also case-sensitivity). Instead i would use the ID. You can always use `Dim rowView As DataRowView = CType(e.Row.DataItem, DataRowView)` to get the actual DataRow and access values that aren't avaiable in the Grid at all. So you don't need HiddenFields or evaluate text. Apart from that i would recommend to use the debugger further. You can set breakpoints and evaluate all you want(even things that are not part of your code, f.e. to trial&error with `FindControl`). – Tim Schmelter Feb 15 '12 at 16:08
  • Oh yeah, I forgot about the that DataRowView thing....when I tried that earlier it told me that e.Row is not a member of DataListItemEventArgs – Jamie Feb 15 '12 at 16:19
  • @jlg: Sorry, i'm mixing DataList with GridView, hence replace all `e.Row....` with `e.Item....` (works similar) – Tim Schmelter Feb 15 '12 at 16:21
0

Try li.FindControl("Label3") instread of e.Item.FindControl("Label3")

Razoomnick
  • 304
  • 4
  • 5