How to change the text of multiple labels using a loop - asp.net

I am trying to change labels in an asp.net web form. My label IDs are lbl1, lbl2, lb3, etc.
con.Open()
For i = 1 To 6
SQL = "SELECT Question FROM Question WHERE TestID=" & Session("TestID") & " AND QuestionID=" & Convert.ToString(i) & ";"
Dim cmd As New OleDbCommand(SQL, con)
Dim myControl As Control = FindControl("ContentHolder_" & "lbl" & Convert.ToString(i))
myControl.Text() = cmd.ExecuteScalar
Next
con.Close()
This obviously doesn't work as .Text is not a property of myControl.
I couldn't work out how to work around this problem.
p.s. I inspected the element of the label in google chrome and found out that it has ContentHolder_ before the name I gave in the id of the element. This is because I use a masterpage and thats why it is there.
Can anyone help?

Control is a base class of all types of webform controls. You need to use the specific type of control you are using. For example, if it is a <asp:Label> control, you need to use the Label type instead of the Control type. Like this:
Dim myControl As Label = CType(FindControl("ContentHolder_" & "lbl" &
Convert.ToString(i)), Label)
myControl.Text = "whatever"
There is a second thing wrong with your code, however. You are putting your SQL query in a loop. You should always try to reduce the number of round trips to your database. In this case, that means changing your code to query the database once, and then using an OleDbDataReader to read the data back. Your code will perform much faster that way.

Related

Access 2010: Display contents of multiple records to unbound controls in datasheet

I'm using a dynamic pass-through query in Access 2010 to retrieve one or more records from a back-end database. After much trial and error, I plagiarized enough of the right code to retrieve the appropriate records and assign them to unbound text-boxes on my datasheet form during an OnLoad event. The only problem remaining is in displaying multiple records. I've verified that I AM retrieving multiple records, but the contents of each record's fields overwrite the previous values stored to the form's textbox controls, so I always end up with just a single record displayed in my datasheet when I expect to see anywhere from one to 10.
I'm sure it's a simple solution. Can someone please point it out to me?
Private Sub Form_Load()
Dim sqlString As String
sqlString = "SELECT Transmitter_ID, Receiver_ID, UTC_Date, Local_Date from Detections"
If Not IsNull(Me.OpenArgs) Then
sqlString = sqlString & " where " & OpenArgs
End If
Dim cnn As New ADODB.Connection
Dim cmd As New ADODB.Command
Dim rst As ADODB.Recordset
'Define and open connection
cnn.ConnectionString = "DRIVER={SQLite3 ODBC Driver};Database=z:\EWAMP\EWAMP_be_dev.sqlite"
cnn.Open
'Define ADO command
cmd.ActiveConnection = cnn
cmd.CommandText = sqlString
'Populate and enumerate through recordset
Set rst = cmd.Execute
If rst.EOF Then
MsgBox "Nothing found...", vbInformation + vbOKOnly
Exit Sub
Else
Do While Not rst.EOF
'// I'm guessing the problem is with my control assignments, here.
Me.cntl_Receiver_ID.Value = rst("Receiver_ID")
Me.cntl_Transmitter_ID.Value = rst("Transmitter_ID")
Me.cntl_UTC_Date.Value = rst("UTC_Date")
Me.cntl_Local_Date.Value = rst("Local_Date")
Debug.Print {Show me the four control values}
rst.MoveNext
Loop
End If
End Sub
Cheers!
DUHdley
I don't believe a form in Datasheet view can be used as an unbound form. But you can use the ADO recordset as the forms recordset.
Set Me.Recordset = rst
Then just be careful not to close your variable named rst until the form closes.
Another alternative solution is to use an in-memory, fabricated, disconnected ADO recordset. Basically, you'd end up creating a new recordset, append fields to it to match your existing recordset, and then move all the data into your new recordset. But I really don't see the point in doing this if you already have a valid, filled ADO recordset.
If you really need/want to display multiple records in an unbound form, I think you would have to use ActiveX controls such as the GridView, ListView, TreeView, or MSFlexGrid. I've noticed that most skilled, professional Access developers stay away from ActiveX controls as much as possible. If and when they do use them, they usually limit it to only the TreeView and the ListView, I think because they are about the only ActiveX controls that add enough value to be worth putting up with whatever problems they might introduce.
I suggest you take a look at this article concerning the differences between DAO and ADO.
http://www.utteraccess.com/wiki/index.php/Choosing_between_DAO_and_ADO
A reader in another forum pointed me to a solution similar to that posed by HK1, namely Set Me.Recordset = rst. That fixed my original problem, but created another.
First I re-bound my four textbox controls on the unbound form, and then modified the code significantly, using the sample from http://msdn.microsoft.com/en-us/library/ff835419.aspx. The revised code looks like this:
Private Sub Form_Load()
Dim sqlString As String
sqlString = "SELECT Transmitter_ID, Receiver_ID, UTC_Date, Local_Date from Detections"
If Not IsNull(Me.OpenArgs) Then
sqlString = sqlString & " where " & OpenArgs
End If
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
'Define and open connection
Set cn = New ADODB.Connection
cn.ConnectionString = "DRIVER={SQLite3 ODBC Driver};Database=z:\EWAMP\EWAMP_be_dev.sqlite;"
cn.Open
'Create an instance of the ADO Recordset class,
'and set its properties
Set rs = New ADODB.Recordset
With rs
Set .ActiveConnection = cn
.Source = sqlString
'// .LockType = adLockOptimistic
.LockType = adLockReadOnly
.CursorType = adOpenKeyset
'// .CursorType = adOpenStatic
.Open
End With
'Set the form's Recordset property to the ADO recordset
Set Me.Recordset = rs
Set cn = Nothing
Set rs = Nothing
End Sub
The form now display four rows for four returned records, 20 rows for twenty records, and on, up to at least 256k rows (as specified by my parameter set). The only remaining teeny tiny problem is that for four or more records, if I press the "last row" navigation button (>|), the local cursor sets focus to one or more of the intermediate rows, and the control's properties sheet refreshes vigorously (multiple times per second). If I have more form rows than can be displayed on the screen, I can not navigate or cursor to the last row. It's as though the record set is constantly being updated.
As you can see, I've played with the RecordSet LockType and CursorType properties (including adOpenDynamic and adOpenForwardOnly, both of which caused a run-time error with the Set Me.Recordset statement). Toggling the LockType between adLockOptimistic and AdLockReadOnly, and the CursorType between adOpenKeyset and adOpenStatic makes no difference in the retrieval performance (which is fantastically fast now!) or the apparent refresh rate (which is even faster, unfortunately).
Perhaps it's worth mentioning that the "Detections" table the sqlString "selects" from contains ~4M records. I was frustrated in my previous attempts to use a form with a data source bound to a passthrough query of this table, because the query always returned the entire 4M records to the client regardless of the filter/WhereClause/OpenArgs parameter I passed to the form. The solution shown above would be perfect if only I could close the connection (I've tried) or otherwise quiesce the RecordSet after I've invoked it once.

Dynamically Adding Multiple User Controls vb.net

I have a User Control which returns a table of data, which in some cases needs to be looped, displaying one on top of another.
I am able to dynamically add a single instance of this by placing a fixed placeholder in the page.
I am now trying to work out how to add more than one, given that I don't know how many might be needed I don't want to hard code the Placeholders.
I've tried the following, but I am just getting one instance, presumably the first is being overwritten by the second
My HTML
<div id="showHere" runt="server"/>
VB
Dim thisPh As New PlaceHolder
thisPh.Controls.Add(showTable)
showHere.Controls.Add(thisPh)
Dim anotherPh As New PlaceHolder
anotherPh .Controls.Add(showTable)
showHere.Controls.Add(anotherPh)
How do I make it add repeated tables within the showHere div?
I would advise generating a different ID for each of your table. For example,
Dim i As Integer
i = 0
For each tbl in ShowTables
tbl.ID = "MyTab" + i.ToString()
i = i + 1
showHere.Controls.Add(tbl)
showHere.Controls.Add(New LiteralControl("<br />"))
Next
On other hand, it would make more sense to have a your user/custom control generate html for a single table and then nest your user/custom control within a repeater (or similar control such as ListView etc).
Did you tried simply, this:
For each tbl in ShowTables
showHere.Controls.Add(tbl)
showHere.Controls.Add(New LiteralControl("<br />"))
Next
After fussing with this issue myself, I stumbled across below solution.
On button click()
LocationDiv.Visible = True
Dim existingItems As New List(Of Object)
If Not Session("existingItems") Is Nothing Then
existingItems = CType(Session("existingItems"), List(Of Object))
For Each item As Object In existingItems
LocationDiv.Controls.Add(item)
Next
existingItems.Clear()
End If
LocationDiv.Controls.Add(New LiteralControl("<b>" & Text & "</b>"))
For Each item As Object In LocationDiv.Controls
existingItems.Add(item)
Next
Session.Add("existingItems", existingItems)

How to reference dynamic textboxes created at run time?

I have an ASP project which references a WCF service. Does exactly half of what I need.
A button on the page calls a function from the WCF, which returns a list of objects (variable names). When returned, the vb code dynamically adds textboxes to a panel on the page. Like this:
For Each LetterVariables In LetterVarList
tb = New TextBox
lb = New Label
lb.Text = LetterVariables._key & " "
tb.ID = LetterVariables._key
pnlVars.Controls.Add(lb)
pnlVars.Controls.Add(tb)
Dim LineBreak As LiteralControl = New LiteralControl("<br />")
pnlVars.Controls.Add(LineBreak)
Next
Now the problem is, after this is finished the user will enter some values into those texboxes. I (somehow) need to reference those texboxes to snag the values when a user clicks another button.
How can I do this?
Thanks,
Jason
You can give the TextBox an ID which you could use FindControl to retrieve.
tb.ID = "txt" + LetterVariables._key.ToString();
Then when you want to reference it.
TextBox txtBox = (TextBox)FindControl("txt" + someKey);
Something like that might work for you.
Don't forget to recreate the controls on post back BEFORE the controls are loaded with the posted values.

Dynamic ID name in ASP.NET VB.NET

I have about 20 asp:labels in my ASP page, all with ID="lbl#", where # ranges from 0 to 22. I want to dynamically change what they say. While I could write
lbl1.Text = "Text goes here"
for all 23 of them, I'd like to know if there is a way to loop through all of them and change their text.
I thought of creating an array with all my labels, and then just do a For Each loop, but I also have to check if the element exists with IsNothing before I change its text, so I got stuck there.
If anyone can help me, I'd really really appreciate it!
Thank you so so much for your help!!
You can dynamically look up controls on the page by using the System.Web.UI.Page.FindControl() method in your Page_Load method:
Dim startIndex As Integer = 0
Dim stopIndex As Integer = 22
For index = startIndex To stopIndex
Dim myLabel As Label = TryCast(FindControl("lbl" + index), Label)
If myLabel Is Nothing Then
Continue For
End If
myLabel.Text = "Text goes here"
Next
Something like this may work, but you would likely need to tweak it (its from memory, so its not exactly 100% syntactically correct)
For Each _ctl as Control In Me.Controls()
If (TypeOf(_ctl) Is Label) = False Then
Continue For
End If
'add additional filter conditions'
DirectCast(_ctl, Label).Text = "Text Goes Here"
Next
You can also do something similar on the client side using jQuery selectors.

How do I get all the values in a listbox when looping through them?

I'm currently trying to move through all the values added to a listbox by the user, however, I want to retrieve the actual value of each item in the listbox and not the text.
I've gotten so far with the code below, but that only gets the text and not the value.
For Each item In SelectedStoresLB.Items
Dim tCompany As Integer = CInt(Left(item.ToString, 1))
Dim tStore As String = Right(item.ToString, 3)
Dim tReason As String = ReasonTxt.Text
insertSQL = "INSERT INTO [CommsDownLog] ([DimCompanyID],[PervasiveStoreNumber],[DownReason]) VALUES (" & tCompany & ", '" & tStore & "', '" & tReason & "')"
Dim insertRow = New SqlCommand(insertSQL, objConn)
Try
objConn.Open()
insertRow.ExecuteNonQuery()
objConn.Close()
Catch ex As Exception
Response.Write(ex)
End Try
Next
How would I go about getting the value for each item in the collection?
item is a ListItem object - rather than call ToString on it, you should use the Text and Value properties to get the info you need.
Using VB 2010, note to get the actual values of the items in the listbox you need to use the "Content" property of the ListBoxItem object. Eg:
For i As Integer = 0 To lstSortUs.Items.Count - 1
sAllItems &= lstSortUs.Items(i).Content & ";"
Next
sAllItems = Left(sAllItems, Len(sAllItems) - 1)
arrAllItems = sAllItems.Split(";")
System.Array.Sort(arrAllItems)
Have you tried:
item.Value
You need to be careful when iterating over a ListBox because you may end up modifying the underlying collection. By using foreach as you are, you are utilizing the underlying enumerator. I recommend you modify your iterator to the following (C# example):
foreach (ListItem li in listbox.Items.ToArray())
{
if (li.Selected)
{
Controltest2.Remove(li.Value);
}
}
By doing this, you are modify the Array's collection and not the list's collection. This assumes LINQ to object and you may need to call Cast<t> to make it work in some cases.
The reason for this is below:
The foreach statement repeats a group
of embedded statements for each
element in an array or an object
collection. The foreach statement is
used to iterate through the collection
to get the desired information, but
should not be used to change the
contents of the collection to avoid
unpredictable side effects
Source: MSDN
To get the text you want after iterating, use .Value instead of .Text. Of course, there are other ways to iterate such as going in reverse with an indexed for loop, but that's another topic :)

Resources