Reading data in a listview without a selection - asp.net

I have a timer running on an Update Panel with a Listview showing a page size of 1. The timer increments the data pager as it cycles through many records.
In the Protected Sub timer_Tick Event I would like to read a few values from the ListView Page. Is there an easy way to do this?
The data is currently binding via a SQLDataSource, but this is temporary while other page development is underway. So I cannot rely on that data set for getting the info needed.
Something like....
val1 = listviewName.SelectedItems(0).SubItems(3).Text
val2 = listviewName.SelectedItems(0).SubItems(4).Text
One issue is that the record will not be selected. The Listview is displaying the data set in an ItemTemplate.
<ItemTemplate>
<tr>
<td>Position C:</td>
<td><asp:Label ID="Label50" runat="server" Text='<%# Eval "Pos_C") %>' />
</td>
</tr>
<tr>
<td>Position D</td>
<td><asp:Label ID="Label51" runat="server" Text='<%# Eval("Pos_D") %>' />
</td>
</tr>
</ItemTemplate>
Abbreviated layout of itemtemplate.

For anyone interested, I solved the above question with the code below....
Protected Sub ListView1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs) Handles ListView1.ItemDataBound
'Get the item object.
Dim dataItem As ListViewDataItem = CType(e.Item, ListViewDataItem)
Dim item As ListViewItem = e.Item
' Get the Label control in the item.
Dim myVal1Lbl As Label = CType(item.FindControl("Label50"), Label)
Dim myVal2Lbl As Label = CType(item.FindControl("Label51"), Label)
Dim myVal1 As String = myVal1Lbl.Text
Dim myVal2 As String = myVal2Lbl.Text
End Sub
Works great.

Related

How to Bind dynamic Data of objects in vb .net or on .aspx page?

I have a Table of Subject Marks and it is dynamic , I want to bind this data on my .aspx page and also want to save or edit these data into database from the page .
Table : SubjectMarks
Subject Marks
English 70
Math 80
Science 90
History 60
I want to save on the page like :
English
70 will be in textbox here
Math
80
Science
90
History
60
I can change the marks data from the textboxes and save the update ones into databse.
Please help me to find this stuff in asp.net. I have .aspx page and backend in .vb
Ok, there are MANY ways to do this.
And you can even use/get the wizards to wire up editing for you. However, I find the built in template editing system REALLY messy to work with.
Having come from desktop land (VB6, ms-access, foxpro), then I want to NOT have to write whacks of code, and I want mostly a drag + drop like easy experience.
So, how to edit some marks for a student that is taking some classes?
Well, I would assume in our database we have Students and StudentCourse table.
(lets keep this simple!)
So, say we have this:
Ok, so we need a combo box to select a student, and then display their courses.
So, first would be say a simple combo box (dropdown) to select a student.
Then we could display the courses, and let you edit the marks. And then an easy save button to save our edits.
Ok, so lets drop in the drop down (combo box). To select the student, and then drop in a gridview for the courses (for display and edit).
And then let’s drop in a button (for saving the edits).
In fact, in place of gridview, lets use a listview. They are VERY similar, but I like listview more since it allows use of standard controls being dropped into the grid display with LESS mess then the gridview. (but, either choice works – I just like the listview better. And it has FAR more customizing abilities. So time spent learning the lv is well worth it.
So, we have this simple markup:
<div style="margin:20px">
<asp:Label ID="Label1" runat="server" Text="Select Student: " Font-Size="Large"></asp:Label>
<asp:DropDownList ID="cboStudents" runat="server" Style="font-size:large;width:180px;margin-left:5px"
AutoPostBack="true"
DataTextField = "FullName"
DataValueField ="ID">
</asp:DropDownList>
<br />
<br />
<div style="width:25%;border:solid;border-width:thin">
<style> input {border:none}</style>
<asp:ListView ID="LstMarks" runat="server" DataKeyNames="ID" >
<ItemTemplate>
<tr style="">
<td><asp:Textbox ID="Course" runat="server" Text='<%# Eval("Course") %>' /></td>
<td><asp:Textbox ID="Mark" runat="server" Text='<%# Eval("Mark") %>' Width="30px"/></td>
<td>
<asp:CheckBox ID="DoneLabs" runat="server" Checked = '<%# Eval("DoneLabs") %>' Width="30px"/>
</td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table id="itemPlaceholderContainer" runat="server" border="0" class="table">
<tr runat="server" style="">
<th runat="server" >Course</th>
<th runat="server">Mark</th>
<th runat="server" >Completed Lab Work</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</LayoutTemplate>
</asp:ListView>
</div>
<br />
<asp:Button ID="cmdSave" runat="server" Text="Save" class="btn"/>
<asp:Button ID="cmdAdd" runat="server" Text="Add Course" class="btn" Style="margin-left:20px" />
<asp:Button ID="cmdUndo" runat="server" Text="Undo Edits" class="btn" Style="margin-left:20px" />
</div>
Ok, so lets write code to fill up that combo box.
In Project Settings, we add the database connection string here:
(it puts in in web config for you - but this way is OH so much easy - and you get to use the connection string builder).
Ok, so now lets write code to load up the combo box
we have this:
Dim rstMarks As New DataTable
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
cboStudents.DataSource =
MyRst("SELECT *, FirstName + ' ' + LastName AS FullName from Students ORDER BY FirstName")
cboStudents.DataBind()
cboStudents.Items.Insert(0, "")
Else
rstMarks = ViewState("MyMarks")
End If
End Sub
So in above, we load up our combo box, and we ALSO have a table for the marks table (and we persisted the rstMarks table - since we need it for editing).
Ok, so we select a student, and fill the list view.
That code looks like this:
Protected Sub cboStudents_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboStudents.SelectedIndexChanged
LoadMarks()
End Sub
Sub LoadMarks()
Dim strSQL As String
strSQL = "SELECT * from StudentCourses WHERE Student_ID = " & cboStudents.SelectedValue &
" ORDER BY Course"
rstMarks = MyRst(strSQL)
LstMarks.DataSource = rstMarks
LstMarks.DataBind()
ViewState("MyMarks") = rstMarks
End Sub
Our output is now this:
So you can now tab around, set the course name, mark, and I tossed in for fun a check box for having completed "lab" work.
So, now we need our save button code. After the user tabs around, edits any mark, or changes a check box, we have to send the edits back to the database.
That code looks like this:
Protected Sub cmdSave_Click(sender As Object, e As EventArgs) Handles cmdSave.Click
GridToTable()
SaveToDB()
End Sub
Sub GridToTable()
' move grid edits back to table.
For Each gRow As ListViewItem In LstMarks.Items
Dim OneRow As DataRow = rstMarks.Rows(gRow.DataItemIndex)
OneRow("Course") = CType(gRow.FindControl("Course"), TextBox).Text
OneRow("Mark") = CType(gRow.FindControl("Mark"), TextBox).Text
OneRow("DoneLabs") = CType(gRow.FindControl("DoneLabs"), CheckBox).Checked
Next
End Sub
Sub SaveToDB()
Using cmdSQL As New SqlCommand("SELECT * FROM StudentCourses WHERE ID = 0",
New SqlConnection(My.Settings.TEST4))
Dim da As New SqlDataAdapter(cmdSQL)
Dim daSQL As New SqlCommandBuilder(da)
da.Update(rstMarks)
End Using
End Sub
So what the above does? It moves grid values back to the table.
THEN Sends the data table (with edits, or even new rows added) back to the database.
And that is quite much it.
I tossed in a add course button, and code for that is this:
Protected Sub cmdAdd_Click(sender As Object, e As EventArgs) Handles cmdAdd.Click
GridToTable() ' user might have made edits - send them to table
' add a new row to table
Dim OneRow As DataRow = rstMarks.NewRow
OneRow("Student_ID") = cboStudents.SelectedItem.Value
OneRow("DoneLabs") = False
OneRow("Mark") = 0
rstMarks.Rows.Add(OneRow)
LstMarks.DataSource = rstMarks ' send table to grid
LstMarks.DataBind()
End Sub
And I did create a helper routine to get data into a table, and that code was:
Function MyRst(strSQL As String) As DataTable
Dim rstData As New DataTable
Using cmdSQL As New SqlCommand(strSQL, New SqlConnection(My.Settings.TEST4))
cmdSQL.Connection.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
Return rstData
End Function
And the un-do edits button? It just re-loads the grid without saving, and thus is this:
Protected Sub cmdUndo_Click(sender As Object, e As EventArgs) Handles cmdUndo.Click
LoadMarks()
End Sub
(it just does the SAME thing as selecting a student in the combo box.
So, the above is FULL of great ideas on how to do this.
And really, it not a lot of code, and you can quite much use the above approach for just about any kind of data editing you need.

How to get Repeater's current ItemIndex in code behind

While Container.ItemIndex as a way to get current repeater's item index in data binding expression works perfectly fine <%# Container.ItemIndex %>, it does not work in pure code behind. Container is not declared or inaccessible.
How can I get repeater's current item index here:
<ItemTemplate>
<% If Container.ItemIndex = 2 Then %>
TRUE/some longer HTML here/
<% Else %>
false/some longer HTML here/
<% End If %>
</ItemTemplate>
EDIT
For cases with not much HTML code this will work, but I am looking for Code Render Block solution as per example above.
<%#: If(Container.ItemIndex = 2, "TRUE", "false") %>
Ok, just drop in a button and pick up the repeter row.
So, say we have this repeater markup:
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<div style="border-style:solid;color:black;width:290px;float:left;padding:10px">
<div style="padding:5px;text-align:right">
Hotel Name: <asp:TextBox ID="txtHotelName" runat="server" Text ='<%# Eval("HotelName") %>' />
<br />
First Name: <asp:TextBox ID="txtFirst" runat="server" Text ='<%# Eval("FirstName") %>' />
<br />
Last Name: <asp:TextBox ID="txtLast" runat="server" Text ='<%# Eval("LastName") %>' />
<br />
City: <asp:TextBox ID="City" runat="server" Text ='<%# Eval("City") %>' />
<br />
Province: <asp:TextBox ID="Province" runat="server" Text ='<%# Eval("Province") %>'/>
<br />
Active: <asp:CheckBox ID="chkActive" runat="server" Checked = '<%# Eval("Active") %>'/>
<br />
<asp:Button ID="cmdRowC" runat="server" Text="Row Click" OnClick="cmdRowC_Click"/>
</div>
</div>
<div style="clear:both;height:5px"></div>
</ItemTemplate>
</asp:Repeater>
and our code behind to fill this repeater:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Using cmdSQL As New SqlCommand("SELECT * FROM tblHotels ORDER BY HotelName",
New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
Repeater1.DataSource = cmdSQL.ExecuteReader
Repeater1.DataBind()
End Using
End Sub
And we now have this:
So now the button code. Note how I just dropped in a standard button.
But, we now can't double click on the button to automatic wire up and create a event.
BUT YOU CAN do this to create a event:
In the button code markup, type in OnClick=
WHEN YOU HIT "=", then intel-sense will pop up a dialog for you to create a button click event like this:
So, now click on create new event. It "seems" like nothing occured, but if we flip to code behind you find the click event stub.
So, now in our click event code we can easy pick up the current repeater row, the values and yes even the index.
The code works like this:
Protected Sub cmdRowC_Click(sender As Object, e As EventArgs)
Dim cBtn As Button = sender
Dim rRow As RepeaterItem = cBtn.Parent
Debug.Print("Row clicked = " & rRow.ItemIndex)
Debug.Print("First Name = " & DirectCast(rRow.FindControl("txtFirst"), TextBox).Text)
Debug.Print("Last Name = " & DirectCast(rRow.FindControl("txtLast"), TextBox).Text)
Debug.Print("Hotel Name = " & DirectCast(rRow.FindControl("txtHotelName"), TextBox).Text)
End Sub
output:
Row clicked = 1
First Name = Darcy
Last Name = Caroll
Hotel Name = Athabasca Hotel
So, just drop in a plane jane button. When you click on it the event stub runs, and as you can see, we pick up the "Repeater row item".
From that row, we can get the row index, and of course pluck out any other control value from that row using find control.
eg:
Dim txtHotel as TextBox = rRow.FindControl("txtHotel")
debug.print ("Hotel name = " & txtHotel.Text)
So, once you have the repeater row, you don't need some container.ItemIndex expression, since the row item lets you get the given index row with:
rRow.ItemIndex
So, ItemIndex is available, and is avilable regardless if you have or include or use the conttin.ItemIndex in the markup.
There is VERY LITTLE need to mess around with that code in the markup.
Note how VERY clean and simple the above is. I suggest you MAKE HUGE efforts to avoid dumping vb code inside of the markup like you are doing. If you even want to convert to c#, or even just maintain that code? Put that code in the code behind area - not in the markup.
As above shows, for repeating data etc., you can use a Repeater, or even often I use a listview - as it allows a repeating layout to be created automatic for you, and without having to write looping code.
******************** EDIT ***************************
Ok, now that we have this working, say we wanted to put in a message in the repeater that
This hotel is Active
or
This hotel is NOT active!
Ok, so in our markup, we could drop in a label like this:
And now from the repeater property sheet, double click here to create the item data bound event:
It is now a simple matter to put in our code logic for each row like this:
Protected Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
Dim rRow As RepeaterItem = e.Item
Dim ckbox As CheckBox = rRow.FindControl("chkActive")
Dim MyLabel As Label = rRow.FindControl("Label1")
If ckbox.Checked Then
MyLabel.Text = "This Hotel is Active!!!"
Else
MyLabel.Text = "Not active!"
End If
End Sub
And output is now this:
So, once again, to conditional format the repeater, add color to active hotel, or whatever? Use the item bound event.
Say i wanted add to above that the HotelName is to be color blue when active, then we could do this:
Protected Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs) Handles Repeater1.ItemDataBound
Dim rRow As RepeaterItem = e.Item
Dim ckbox As CheckBox = rRow.FindControl("chkActive")
Dim MyLabel As Label = rRow.FindControl("Label1")
If ckbox.Checked Then
MyLabel.Text = "This Hotel is Active!!!"
Else
MyLabel.Text = "Not active!"
End If
Dim txtHotel As TextBox = rRow.FindControl("txtHotelName")
If ckbox.Checked Then
txtHotel.BackColor = Drawing.Color.AliceBlue
End If
End Sub
Again, nice easy clean code - no mess markup. We seperate the code logic from the markup.
Output now is this:
Again, note how we did not even write ANY looping code here!!!!
So you want to leverage the built in options for the repeater, and for a GridView, listView, and a repeater?
Use the row data bind event - it lets you format, even do math, or whatever you want for EACH row of the repeating controls. And as you can see, its plain jane easy to write code as a bonus.

Listview DropDownList FindControl without Edit Button

I am having trouble populating a dropdownlist from a dataset when the dropdownlist is embedded in a listview. I get "Object reference not set to an instance of an object." because, I believe, I am not accessing the dropdownlist correctly using FindControl
We do NOT want edit buttons on this listview, we want every line to be editable at once. Most examples online have edit buttons. That might be part of my problem.
Most examples online also use a datasource defined in the ASPX page. We've been using exclusively Oracle.DataAccess sys_refcursor to populate datasets, and then use the dataset as the datasource. So I have to populate the drop down from the VB side, not but using a datasource in the aspx page.
I can independantly populate a listview, and independantly populate a dropdownlist, but walking and chewing gum is a failure.
So here are some snippets of what I got:
<asp:ListView ID="lvMFGRS" runat="server">
<ItemTemplate>
<tr runat="server">
<td runat="server">
<asp:Label ID="NameLabel" runat="server" Text='<%#Eval("NEW_MANUFACTURER")%>' />
</td>
<td runat="server">
<asp:dropdownlist ID="ddMFGRS" runat="server" />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
Then something like this on the vb side:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
newmfglist() 'just sticks data in the "NameLabel" and databinds, and this works fine.
For Each lvItem In lvMFGRS.Items
Dim ddlist As DropDownList = lvMFGRS.FindControl("ddMFGRS")
For Each tbl2 As DataTable In dsmfgrlist.Tables
For Each dr2 As DataRow In tbl2.Rows
Dim str1 As String
Dim str2 As String
str1 = "dog" 'dr2.Field(Of String)("DataValueField")
str2 = "cat" 'dr2.Field(Of String)("DataTextField")
ddlist.Items.Add(New ListItem(str2, str1)) 'this is where I get the error
Next
Next
Next
End Sub
So what do you think I'm doing wrong...
The answer is:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
newmfglist() 'just sticks data in the "NameLabel" and databinds, and this works fine.
For Each lvItem In lvMFGRS.Items
Dim ddlist As DropDownList = lvItem.FindControl("ddMFGRS")
For Each tbl2 As DataTable In dsmfgrlist.Tables
For Each dr2 As DataRow In tbl2.Rows
Dim str1 As String
Dim str2 As String
str1 = "dog" 'dr2.Field(Of String)("DataValueField")
str2 = "cat" 'dr2.Field(Of String)("DataTextField")
ddlist.Items.Add(New ListItem(str2, str1)) 'this is where I get the error
Next
Next
Next

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.

Looping through a repeater control to get values of Textbox in asp.net

I am trying to loop through my repeater control and get the textbox values.
However, I am getting an error:
{"Object reference not set to an instance of an object."}
my code is:
Dim txtField As TextBox
Dim j As Integer = 0
'Confirm if user has entered atleast one quantity
For Each item In rptRequestForm.Items
txtField = rptRequestForm.FindControl("txtBox")
If txtField.Text <> Nothing Then
j += 1
Else
End If
Next
UPDATE: aspx code is:
<td><asp:Repeater ID="rptRequestForm" runat="server">
<HeaderTemplate>
<table border="0" width="100%">
<tr>
<td style="width:50%" class="TextFontBold"><asp:Label runat="server" ID="Label1" Text="Product"></asp:Label></td>
<td style="width:25%" class="TextFontBold"><asp:Label runat="server" ID="Label2" Text="Quantity"></asp:Label></td>
<td style="width:25%" class="TextFontBold"><asp:Label runat="server" ID="Label3" Text="Price (ea.)"></asp:Label></td>
</tr>
</table>
</HeaderTemplate>
<ItemTemplate>
<table border="0" width="100%">
<tr>
<td style="width:50%" class="TextFont"><span><%#Trim(Eval("Product_Title"))%></span></td>
<td style="width:25%"><asp:TextBox ID="txtBox" runat="server" Width="30%" onblur="Javascript:numberonly(this)"></asp:TextBox></td>
<td style="width:25%" class="TextFont"><span><%#Trim(FormatCurrency(Eval("Price")))%></span></td>
</tr>
</table>
</ItemTemplate>
</asp:Repeater>
try
Dim someString as String = "Not set" <-- used later to hold the values of the string
Dim txtField As TextBox
Dim j As Integer = 0
'Confirm if user has entered atleast one quantity
For Each item In rptRequestForm.Items
txtField = item.FindControl("txtBox")
If Not IsNothing(txtField) Then ' <--- this is the line I changed
j += 1
someString = txtField.Text ' <-- once you've checked and know that the textbox exists, you just grab the value like so.
' do whatever you like with the contents of someString now.
Else
End If
Next
The problem is that you're trying to access the ".Text" property of a TextBox that it didn't find. The TextBox itself is the object to which there is no reference.
Incidentally, the .Text property of an actual Textbox (one that exists and was found) can't be "Nothing". It can only be String.Empty or a valid string.
Edited my line of code
Sorry, my VB is rusty.
Final edit
AARGH! I'm blind. I can't believe I didn't see this. There were TWO problems withthe original code. This is the answer to the second issue:
Change
txtField = rptRequestForm.FindControl("txtBox")
to
txtField = item.FindControl("txtBox")
The ITEM has to find the control, not the repeater itself!
I created a small web app just to check to see if I was grabbing the textbox's text and finally found the issue above. my code is NOT the same as yours in the aspx, but here's a complete code listing so that you can see how it works:
vb code
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim t As New System.Data.DataTable
t.Columns.Add("Name")
Dim newRow(1) As Object
t.Rows.Add(New Object() {"Frank"})
t.Rows.Add(New Object() {"Dave"})
t.Rows.Add(New Object() {"Muhammad"})
rptRequestForm.DataSource = t
rptRequestForm.DataBind()
Dim txtField As TextBox
Dim j As Integer = 0 'Confirm if user has entered atleast one quantity
For Each item As RepeaterItem In rptRequestForm.Items
txtField = item.FindControl("txtBox")
If Not IsNothing(txtField) Then ' <--- this is the line I changed
j += 1
System.Diagnostics.Debug.WriteLine(item.ItemType.ToString())
System.Diagnostics.Debug.WriteLine(txtField.Text)
Else
System.Diagnostics.Debug.WriteLine(item.ItemType.ToString())
End If
Next
End Sub
aspx code
<asp:Repeater ID="rptRequestForm" runat="server">
<HeaderTemplate>
Hello!
</HeaderTemplate>
<ItemTemplate>
<asp:TextBox ID="txtBox" runat="server" Text='<%#Bind("Name") %>'></asp:TextBox>
<br />
</ItemTemplate>
</asp:Repeater>
produces the following output in the System.Diagnostics.Debug window:
Item
Frank
AlternatingItem
Dave
Item
Muhammad
The thread 0x321c has exited with code 0 (0x0).
The thread 0x39b8 has exited with code 0 (0x0).
You have to properly cast it as Textbox e.g.
TextBox txtField = (TextBox)rptRequestForm.FindControl("txtBox") // C# code
Here is VB.NET code:
Dim txtField As TextBox = CType(rptRequestForm.FindControl("txtBox"), TextBox)
Dim myText as string
Dim j As Integer = 0
'Confirm if user has entered atleast one quantity
For Each myItem as repeateritem In rptRequestForm.Items
If NOT string.isnullorempty(CTYPE(myItem.FindControl("txtBox"),textbox).text) then
j += 1
End If
Next
I wouldn't use nothing -- not sure that causes a problem or not, but usually I see that for objects, not properties. String.IsNullOrNothing() is made for checking strings for null or empty ("").
You don't need to worry about whether or not the textbox exists, because if it exists in one row of the repeater, it will exist in all rows. I guess you could check it for 'nothing' if you weren't sure what "txtBox" was at design time...but otherwise, not necessary.
You should definately use the cast (CTYPE()). I think you might be able to get away with not using it if all you want is .text, but the CTYPE gives you access to all of the textbox's properties (not just it's inherited properties), and also, you might need to do checkboxes or other controls at some point where you pretty much have to CTYPE in order to get to .ischecked, etc.
I made a generic method for set the property visible, I think you can take it as an example
Sub SetVisibleControlRepeater(ByRef repetidor As Repeater, ByVal idControl As String, ByVal esVisible As Boolean)
For Each item As RepeaterItem In repetidor.Items
Dim boton As System.Web.UI.WebControls.Button = CType(item.FindControl(idControl), Button)
boton.Visible = esVisible
Next
End Sub

Resources