ModalPopupExtender loses dynamically-added table rows on button click - asp.net

VS 2013, ASP.NET 3.5 VB.NET
Page has multiple ModalPopupExtender controls for different popups. One of these popups fills a table with CheckBoxControls and descriptions for up-selling items.
Page Code:
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajax" %>
[snip]
<ajax:ModalPopupExtender
runat="server"
ID="mpeUpsell"
popupControlID="pUpsell"
CancelControlID="bGoBack"
BackgroundCssClass="custBackground"
PopupDragHandleControlID="phDragUpsell"
TargetControlID="bHidden"
Enabled="True" />
<asp:Panel runat="server" ID="pUpsell" style="display:none;">
<div runat="server" class="custPopup">
<div runat="server" id="phDragUpsell">
<h3 style="text-align:center;">
<asp:Label
ID="lUpsellHdr"
runat="server"
Text="Check Out these Add-Ons" />
</h3>
</div>
<asp:Label
ID="lAddOnsText"
runat="server" />
[snip]
<asp:Table
ID="tItems"
runat="server"
style="border: 1px solid black;">
[snip] <asp:Button ID="bNext" runat="server" Text="Next --->" />
</td>
</tr>
</table>
<br />
<br />
</div>
</asp:Panel>
The table tItems is populated like so:
For Each dr As DataRow In ds.Tables(0).Rows
tr = New TableRow()
tc = New TableCell()
Dim sName As String = "cbItem_" & CInt(dr("ITEM_ID"))
Dim cb As New CheckBox()
cb.ID = sName
cb.Text = dr("ITEM_DESC").ToString.Trim
If CInt(dr("UGICheckOFF")) = 1 Then
cb.Checked = True
Else
cb.Checked = False
End If
[snip formatting]
tc.Controls.Add(cb)
tr.Cells.Add(tc)
tc2 = New TableCell()
Dim sPrice As String = String.Format("{0:C}", dr("ITEM_PRICE"))
tc2.Text = sPrice
[snip formatting]
tr.Cells.Add(tc2)
tItems.Rows.Add(tr)
Next
The table populates perfectly and shows when I use code-behind to show the mpeUpsell ModalPopupExtender.
The bNext button's handler looks like this:
Protected Sub bNext_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles bNext.Click
If iItemArray IsNot Nothing Then iItemArray = Nothing ' get rid of it
' Handle the Next Button
Dim iCartID As Integer = -1
iCartID = CInt(Session("CartID"))
' iterate the items and add each to cart if not already in cart
iItemArray = New ArrayList()
For Each tr As TableRow In tItems.Rows
For Each tc As TableCell In tr.Cells
For Each ctl As Control In tc.Controls
If TypeOf (ctl) Is CheckBox Then
Dim cb As CheckBox = CType(ctl, CheckBox)
If cb.Checked Then
'if there are checks create array of item IDs checked.
Dim itemid As Integer = CInt(cb.ID.Replace("cbItem_", ""))
iItemArray.Add(itemid)
End If
End If
Next
Next
Next
[snip]
End Sub
When the handler is executed, tItems.Rows.Count is ZERO and the ForEach simply falls through because the table rows are gone.
It is obvious that I have missed something; I just cannot figure out what I have missed.
Thanks,
John.

The solution was to abandon the asp table because it is not stateful in this instance. Instead, I used a gridview and bound a datatable to it, and am able to retrieve the values.
Thanks.

Related

how to get all values of selected checkbox in vb.net and set it on string list

I need to get selected items on checkbox and set as string format like (value1,value2,value3) from the checkbox i selected
For Each row As GridViewRow In GridView1.Rows
If row.RowType = DataControlRowType.DataRow Then
Dim CheckRow As CheckBox = (TryCast(row.Cells(1).FindControl("chckSelector"), CheckBox))
If CheckRow.Checked Then
Dim scode As String = TryCast(row.Cells(2).FindControl("lblsstorecode"), Label).Text
lbltest.Text = 'this i want to get the value like this (value1,value2,value3) from checkbox that i selected
End If
End If
Next
Depending on why you are using the GridView control, you might me able to accomplish this easier by using a CheckBoxList instead. In Asp.net what you describe is accomplished very easily with a CheckBoxList as follows:
In .aspx:
<asp:CheckBoxList ID="Itemlst" runat="server" RepeatColumns="1">
<asp:ListItem Value="">Item 1</asp:ListItem>
<asp:ListItem Value="">Item 2</asp:ListItem>
<asp:ListItem Value="">Item 3</asp:ListItem>
</asp:CheckBoxList>
</br>
<asp:Button ID="Button1" runat="server" Text="Button" />
</br>
<asp:TextBox ID="TextBox1" runat="server" Width="400"></asp:TextBox>
Then in the code behind:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim selected = New List(Of ListItem)
Dim itemcount As Integer
Dim csvlist As String = ""
For Each item As ListItem In Itemlst.Items
If item.Selected Then selected.Add(item)
Next
itemcount = selected.Count
For i = 0 To itemcount - 1
csvlist = csvlist & selected(i).ToString & ","
Next
csvlist = Mid(csvlist, 1, Len(csvlist) - 1)
TextBox1.Text = csvlist
End Sub
The Windows Forms CheckedListBox would probably work similar if you are developing a desktop application.

Unable to Get Element with ID in VB.Net

I have the below code to retrieve the table element when the checkbox is checked.
With this, I could get the table ID. When I try to get the HtmlTable with the ID, it throws the null reference exception.
Once I get the table element with its ID, I need to loop through the rows of that table. Could anyone help me out?
ASPX.VB
Protected Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs)
Dim tab As String
Dim check As CheckBox = CType(sender, CheckBox)
tab = check.Parent.Parent.Parent.ID
Dim tabb As HtmlControl = Me.FindControl(tab)
Dim myTab As HtmlTable = CType(tabb, HtmlTable)
For Each cell As HtmlTableRow In myTab.Rows
//My Code Here
Next
End Sub
ASPX:
<table id="itemlist" class="mel-table" runat="server">
<tr>
<td>
<asp:CheckBox runat="server" ID="CheckBox2" OnCheckedChanged="CheckBox2_CheckedChanged" AutoPostBack="true" />
</td>
</tr>
</table>
Use the parent element ID under which the table is nested like below.
Protected Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs)
Dim tab As String
Dim check As CheckBox = CType(sender, CheckBox)
tab = check.Parent.Parent.Parent.ID
Dim myTab As HtmlTable = CType(mydiv.FindControl(tab), HtmlTable)
For Each cell As HtmlTableRow In myTab.Rows
//My Code Here
Next
End Sub
<div id="mydiv" runat="server">
<table id="itemlist" class="mel-table" runat="server">
<tr>
<td>
<asp:CheckBox runat="server" ID="CheckBox2" OnCheckedChanged="CheckBox2_CheckedChanged" AutoPostBack="true" />
</td>
</tr>
</table>
</div>

Object reference not set to an instance of an object. - Visual Basic (Web)

So, I'm having a slight problem with my code.
I was working on a small school project (recreation of book library) and encountered a problem which I cannot get a grasp of.
So, the user can search for a list of books, and after the list is populated (via DataList control), a small button "Book now" (Reserve) appears which user can click and reserve his book.
This is the code for the DataList control that resides in "Search.aspx"
<asp:DataList ID="DataList1" runat="server" DataKeyField="knjigaId" DataSourceID="SearchSqlDataSource" CssClass="searchControl">
<ItemTemplate>
<div class="pictureOfFoundBook">
<asp:Image ID="pictureOfFoundBook_imageLink" runat="server" ImageUrl='<%#"~/GetImage.aspx?knjigaId=" & Eval("knjigaId") & "&img=naslovnica" %>' />
</div>
<div class="descriptionOfFoundBook">
Naziv: <asp:Label ID="Label1" runat="server" Text='<%# Eval("naziv") %>' /><br />
Godina izdanja: <asp:Label ID="Label2" runat="server" Text='<%# Eval("godinaIzdanja") %>' /><br />
Broj stranica : <asp:Label ID="brojStranicaLabel" runat="server" Text='<%# Eval("brojStranica") %>' /><br />
Izdavač: <asp:Label ID="NazivIzdavacaLabel" runat="server" Text='<%# Eval("NazivIzdavaca") %>' /><br />
Vrsta tiskovine : <asp:Label ID="NazivVrsteTiskovineLabel" runat="server" Text='<%# Eval("NazivVrsteTiskovine") %>' /><br />
Kategorija: <asp:Label ID="NazivKategorijeLabel" runat="server" Text='<%# Eval("NazivKategorije") %>' /><br /><br />
<asp:HyperLink ID="foundBookEditHL_adminOnly" runat="server" NavigateUrl='<%# "~/admin/knjigeEdit.aspx?knjigaId=" & Eval("knjigaId") %>'>Uredi knjigu</asp:HyperLink><br />
<asp:Button ID="rezervacijeButton" runat="server" Text="Rezerviraj" OnClick="rezervacijaClick" CommandArgument='<%# Eval("knjigaId") %>'/><br />
<asp:Label ID="rezStatusLabel" runat="server"></asp:Label>
<asp:PlaceHolder ID="rezStatusPlaceholder" runat="server"></asp:PlaceHolder>
</div>
<hr />
</ItemTemplate>
</asp:DataList>
I've set the DataList1 control as a Friend sub so I can access the controls in it from another sub;
Friend Sub DataList1_ItemCreated(sender As Object, e As System.Web.UI.WebControls.DataListItemEventArgs) Handles DataList1.ItemCreated
End Sub
I was trying to do the following; on the click of a button "rezervacijeButton", a function "rezervacijaClick" runs, which populates the table in the database.
Protected Sub rezervacijaClick(sender As Object, e As System.EventArgs)
Dim Conn As New System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ToString)
Dim cmd As New System.Data.SqlClient.SqlCommand
Dim sql As New StringBuilder
Dim rezstatus As Label = DataList1.FindControl("rezStatusLabel")
sql.Append("INSERT INTO rezervacije(UserName, knjigaId) VALUES (#UserName, #knjigaId)")
Dim buttonsender As Button = sender
cmd.Parameters.AddWithValue("UserName", User.Identity.Name)
cmd.Parameters.AddWithValue("knjigaId", buttonsender.CommandArgument)
Conn.Open()
cmd.CommandText = sql.ToString
cmd.Connection = Conn
cmd.ExecuteNonQuery()
Conn.Close()
buttonsender.Visible = False
rezstatus.Text = "aaa"
'Try
' rezstatus.Text = "testing..."
'Catch ex As Exception
' exlabel.Text = "POGREŠKA"
' exlabel.ForeColor = Drawing.Color.Red
'End
End Sub
The next thing I wanted to do in the function "rezervacijaClick" was to set the text value of the Label (with ID "rezStatusLabel", which resides inside the DataList1 control) to "SOME TEXT" after the "Reserve" button is clicked.
But after the button click, I get the following error :
Object reference not set to an instance of an object.
Line 21:
Line 22: buttonsender.Visible = False
Line 23: rezstatus.Text = "aaa"
Line 24:
Line 25: 'Try
Your rezstatus object is Nothing (null).
This is happening because you aren't looking in the right place for your label.
Each record of data you bind to the DataList will create a new hierarchy of controls, containers that hold the other controls you have defined in your ItemTemplate.
The immediate descendants of DataList1 will be a collection of DataListItem objects and then you will have your controls inside those.
Since we don't know for sure (unless you know you are only binding one record to the DataList) which DataListItem the desired label will be in, we simply walk backwards up the control tree and find the label from there.
Because you are responding to a button click event in your rezervacijaClick method, the parameter sender will be of type Button and will come from rezervacijeButton, so we can use that information to find your label:
Dim clickedButton As Button = CType(sender, Button) 'convert the sender parameter to the correct type: Button
Dim buttonParent As Control = clickedButton.Parent 'get a reference to the button's parent control
Dim rezstatus As Label = CType(buttonParent.FindControl(""), Label) 'find the label by ID and convert it to a Label as the return type of FindControl is Control
I would recommend that, instead of using the Button click event, you use the DataList.ItemCommand event. It will make your life a lot easier. This event fires whenever a Button is clicked within a row of your DataList control.
This way, you get the index passed in through the DataListCommandEventArgs parameter. then you would just need to update your DataList markup to add the event handler:
<asp:DataList ID="DataList1" runat="server" DataKeyField="knjigaId"
DataSourceID="SearchSqlDataSource" CssClass="searchControl"
ItemCommand="DataList1_ItemCommand" >
And your handler code would look like this:
Protected Sub DataList1_ItemCommand(sender As Object, e As System.EventArgs)
Dim Conn As New System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ToString)
Dim cmd As New System.Data.SqlClient.SqlCommand
Dim sql As New StringBuilder
Dim rezstatus As Label = e.Item.FindControl("rezStatusLabel")
sql.Append("INSERT INTO rezervacije(UserName, knjigaId) VALUES (#UserName, #knjigaId)")
Dim buttonsender As Button = e.Item.FindControl("rezervacijeButton")
cmd.Parameters.AddWithValue("UserName", User.Identity.Name)
cmd.Parameters.AddWithValue("knjigaId", buttonsender.CommandArgument)
Conn.Open()
cmd.CommandText = sql.ToString
cmd.Connection = Conn
cmd.ExecuteNonQuery()
Conn.Close()
buttonsender.Visible = False
rezstatus.Text = "aaa"
End Sub

Find the right value of textbox

I have a problem with inserting data inserting data into database.
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
<!-- Some other data (text...) -->
<asp:HiddenField ID="HiddenField1" runat="server" Value='<%# Eval("PostId") %>' />
<asp:TextBox ID="txtAddComment" runat="server" CssClass="textbox" Width="200px" />
<asp:Button ID="btnAddComment" runat="server" CssClass="button" Text="Comment" CausesValidation="false" OnClick="btnAddComment_Click"/>
</ItemTemplate>
</asp:Repeater>
Code behind:
Protected Sub btnAddComment_Click(sender As Object, e As EventArgs)
Dim HiddenField1 As HiddenField = DirectCast(Repeater1.Items(0).FindControl("HiddenField1"), HiddenField)
Dim txtAddComment As TextBox = DirectCast(Repeater1.Items(0).FindControl("txtAddComment"), TextBox)
Dim conn As New SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString.ToString)
Try
If txtAddComment.Text = "" Then
Exit Sub
Else
conn.Open()
Dim cmd As SqlCommand = conn.CreateCommand()
cmd.CommandText = "INSERT INTO Comments (PostId, UserName, CommentText) VALUES (#PostId, #UserName, #Text)"
cmd.Parameters.Add("PostId", System.Data.SqlDbType.Int).Value = CInt(HiddenField1.Value)
cmd.Parameters.Add("UserName", System.Data.SqlDbType.NVarChar).Value = Context.User.Identity.Name
cmd.Parameters.Add("Text", System.Data.SqlDbType.NText).Value = MakeLink(HtmlRemoval.StripTagsCharArray(txtAddComment.Text))
cmd.ExecuteNonQuery()
End If
Catch ex As SqlException
Finally
conn.Close()
End Try
End Sub
I display some text, under the text there is textbox and button for comments. I am bounding textId in hiddenfield for inserting comments. The code works fine, but I can only add comment for the first row in database displayed by repeater. When I want to add comment for other rows (2, 3...), the page refreshes and the text in the TextBox stay there.
It is problem with this line of code:
Dim txtAddComment As TextBox = DirectCast(Repeater1.Items(0).FindControl("txtAddComment"), TextBox)
The ID from HiddenField is right. But the code doesn't perform because the line above references for the first textbox on the page and his value is null.
When I change the line of code like this:
Dim txtAddComment As TextBox = DirectCast(Repeater1.FindControl("txtAddComment"), TextBox)
It returns an error that Object reference not set to an instance of an object.
How to get the right textbox with right value?
Thanks for the answer
cast the sender to a button that sent it, then get the textbox from the parent. Example:
Protected Sub button_click(ByVal sender As Object, ByVal e As EventArgs)
Dim myButton As button= CType(sender, button)
Dim myTextBox as TextBox = CType(myButton Parent.FindControl("buttonName"), TextBox)
end sub

ASP.net dropdownlist unexpected event firing behavior

I'm experiencing some odd behavior with drop down boxes and I'm hoping someone could explain what's going on. I have a datarepeater that builds out a table of rows. Each row has a dropdownlist (hidden) and a linkbutton (not hidden) in a cell. The expected behavior is that when a user clicks the linkbutton for a specific cell, it fires a server command. This command does a few things but also sets the selected value of the DDL and then sets it visible and sets itself (the linkbutton) hidden. The problem is that the dropdownlist's event should fire every time the selected index changes. But, what ends up happening is that it only fires the first time the user changes the DDL value. After that, the event will stop firing. Also, all of this is in a usercontrol and all the code is inside an updatepanel. As I mention in the code example, if I do not change the ddl value, in the linkbutton event, this behaviors stops but then the DDL wont have the correct value set. Here is my code:
Linkbutton event:
Protected Sub edit_click(ByVal sender As Object, ByVal e As EventArgs)
Dim btn As LinkButton = CType(sender, LinkButton)
Dim userId As String = btn.CommandArgument
Dim ds As New List(Of myObject)
Dim currentChoice As New myObject
Dim parent As RepeaterItem = CType(btn.Parent, RepeaterItem)
Dim lbl As Label = CType(parent.FindControl("userId"), Label)
Dim ma As DropDownList = CType(parent.FindControl("ddlMustApprove"), DropDownList)
Dim maLbl As Label = CType(parent.FindControl("mustApprove"), Label)
'just get a list of values to chose from
ds = Session("userNotificationDS")
currentChoice = ds.Find(Function(p As myObject) p.User.NetworkID = userId)
With maLbl
.Width = 100
.BorderColor = Drawing.Color.DarkBlue
End With
'if I disable this next line, everything works fine (but then the correct selection wont be chosen)
ma.Text = currentChoice.MustApprove
ma.CssClass = ""
maLbl.Visible = False
End Sub
DDL change event:
Protected Sub selection_Change(ByVal sender As Object, ByVal e As EventArgs)
Dim cnt As DropDownList = CType(sender, DropDownList)
Dim parent As RepeaterItem = CType(cnt.Parent, RepeaterItem)
Dim maLbl As Label = CType(parent.FindControl("mustApprove"), Label)
Dim userId As Label = CType(parent.FindControl("userId"), Label)
Dim ds As New List(Of myObject)
'just gets the value to set the DDL to
ds = Session("userNotificationDS")
For Each i As myObjectIn ds
If (i.User.NetworkID = userId.Text) Then
i.MustApprove = cnt.SelectedValue
End If
Next
maLbl.Visible = True
cnt.CssClass = "hidden"
Session("userNotificationDS") = ds
bindData(ds)
End Sub
Here is the Datarepeater in the front end code:
<asp:Repeater ID="dataRepeateUsers" runat="server" EnableViewState="false" OnItemCreated="RepeaterItemCreated" >
<HeaderTemplate>
.... column headers
</HeaderTemplate>
<ItemTemplate>
<tr class="listcolor">
<td style="border:0px; border-right:1px solid #808080 ; border-bottom:0px solid #808080;">
<asp:DropDownList runat="server" ID="ddlMustApprove" CssClass="hidden" OnTextChanged="selection_Change" EnableViewState="true" AutoPostBack="true" >
<asp:ListItem Text="True" Value="True"></asp:ListItem>
<asp:ListItem Text="False" Value="False"></asp:ListItem>
</asp:DropDownList>
<asp:label ID="mustApprove" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "MustApprove") %>'></asp:label>
</td>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr class="listcolor">
<td style="border:0px; border-right:1px solid #808080 ; border-bottom:0px solid #808080;">
<asp:DropDownList runat="server" ID="ddlMustApprove" CssClass="hidden" OnTextChanged="selection_Change" EnableViewState="true" AutoPostBack="true" >
<asp:ListItem Text="True" Value="True"></asp:ListItem>
<asp:ListItem Text="False" Value="False"></asp:ListItem>
</asp:DropDownList>
<asp:label ID="mustApprove" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "MustApprove") %>'></asp:label>
</td>
</tr>
</AlternatingItemTemplate>
<FooterTemplate>
</FooterTemplate>
</asp:Repeater>
My code is written in VS 2010 using .Net 4.0 and AjaxControlToolkit 4.1.60919.
Thanks
jason
ma.Text = currentChoice.MustApprove
replace this line with the following one.
if(ma.items.FindByText(currentChoice.MustApprove) != null)
{
ma.SelectedIndex = -1;
ma.items.FindByText(currentChoice.MustApprove).selected = true;
}
Just set the selectedindex of the dropdown as -1 like above.

Resources