this is going to take some explaining.
I have an asp.net page with 2 dropdown lists. These each postback. I am using vb.net for the code behind. I then have a public datatable which stores some values which relate to the dropdownlists.
The table (tblfilters) looks like this:
Index | DBField | DDList |
---|---|---|
0 | PurchaseYear | ddlYOP |
1 | SetNumber | ddlnumber |
The Index datatype is an integer, the DB Field is a string and the DDList is dropdownlist
I can loop through the table records and, using the DDList, bind the values to the controls from SQL which works well. My issue is that I can't seem to get the Selecteditem.Text from the same dropdownlists. If I refer to the controls on the page by ID then I get the selected value however if I try and use the datatable field value all I get back is the top value from the dropdownlist, no matter what is selected.
The binding of the dropdownlists only happens once and is already within the page_load event
If Not IsPostBack Then
For Each row In tblfilters.Rows
BindFilterData(row.Item("DBField"), row.Item("DDList"))
Next
End If
I have tried referencing the DDList values by the following methods:
For Each row In tblfilters.Rows
lbloutput.Text += row.Item("DDList").Selecteditem.Text
Next
or
For Each row In tblfilters.Rows
Dim ddltest as dropdownlist = FindControl(row.Item("DDList"))
lbloutput.Text += ddltest.Selecteditem.Text
Next
It doesn't matter if I've selected anything in the dropdownlist or not I always just get back the first value in the list.
As I say, if I use the following then it works but I really could do with looping through the datatable for what I'm trying to do:
lbloutput.Text += ddlyp.SelectedItem.Text
lbloutput.Text += ddlnumber.SelectedItem.Text
I am sure I'm missing something obvious here and hoping someone can spot the error of my ways.
Thanks in advance
Ok, so the steps in general to display a table in a web form are:
Load up combo box choices into a DataTable for each combo box.
Load the display of the table. This could be a GridView, Listview, Repeater or even an older DataGrid (you not find the DataGrid in the tool box anymore, but in markup they can be used).
For display of a table, then often a GridView is a great choice, but as you have more and more markup and custom controls in that grid display, then I tend to move over to using a ListView, as it has more flexibility for layout and use of controls like a combo box (DropDownList).
So, for this example, we will have a list of people, and for each row of data, we will have a combo box for the city (a simple text column from the database), and second combo box for the hotel selection. In this second combo box, of course we will store/save/use the PK for the hotel choices, but display the HotelName (so, the combo box has 2 values, the hidden PK value of the hotel, then the text value of HotelName). Upon selection of the Hotel combo box, then we will need to save/store the PK value of the hotel selected into the one data row.
So, after we load up the ListView we then have to load up the combo boxes for each row, and THEN an additional step is required to set the current grid row combo boxes to the correct underlying values selected for that row.
So, say this markup:
<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID"
OnItemDataBound="ListView1_ItemDataBound">
<LayoutTemplate>
<table id="itemPlaceholderContainer" runat="server" border="0"
class="table table-bordered table-hover">
<tr runat="server" style="">
<th runat="server" style="width:100px">First</th>
<th runat="server" style="width:100px">Last</th>
<th runat="server" style="width:160px" >City</th>
<th runat="server" style="width:240px">Hotel Name</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr style="">
<td><asp:Label ID="First" runat="server" Text='<%# Eval("FirstName") %>' /></td>
<td><asp:Label ID="Last" runat="server" Text='<%# Eval("LastName") %>' /></td>
<td>
<asp:DropDownList ID="cboCity" runat="server"
DataTextField="City"
width="100%"
>
</asp:DropDownList>
</td>
<td>
<asp:DropDownList ID="cboHotel" runat="server"
DataTextField="HotelName"
DataValueField="ID"
width="100%"
>
</asp:DropDownList>
</td>
</tr>
</ItemTemplate>
</asp:ListView>
So, note how the above has 2 combo boxes (City, and Hotel)
Code behind is thus this:
Dim dtCityList As DataTable
Dim dtHotelList As DataTable
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid
End If
End Sub
Sub LoadGrid()
dtCityList = MyRst("SELECT City FROM City ORDER BY City")
dtHotelList = MyRst("SELECT ID, HotelName FROM tblHotels ORDER BY HotelName")
ListView1.DataSource = MyRst("SELECT * FROM People ORDER BY LastName")
ListView1.DataBind()
End Sub
Protected Sub ListView1_ItemDataBound(sender As Object, e As ListViewItemEventArgs)
If e.Item.ItemType = ListViewItemType.DataItem Then
Dim dRow As DataRowView = e.Item.DataItem ' get binding data source
Dim cboCity As DropDownList = e.Item.FindControl("cboCity")
cboCity.DataSource = dtCityList
cboCity.DataBind()
cboCity.Items.Insert(0, "Select City")
If Not IsDBNull(dRow("City")) Then
cboCity.Text = dRow("City")
End If
Dim cboHotels As DropDownList = e.Item.FindControl("cboHotel")
cboHotels.DataSource = dtHotelList
cboHotels.DataBind()
cboHotels.Items.Insert(0, "Select Hotel")
If Not IsDBNull(dRow("Hotel_ID")) Then
cboHotels.Text = dRow("Hotel_ID")
End If
End If
End Sub
And the result is now this:
So, the important part in above?
We load up 2 data table objects with the combo box selections for each row.
We then load the Grid (a ListView in this example), and on item data bound (that runs for each row), then we load up each combo box (using find control to get a reference for the current row). After setting the combo box list of choices, we then set the current selected combo box value to the current underlying value for that given data row.
So, the above shows all the moving parts you need when having combo boxes on a given row of data.
For completeness, I also used one of my library helper routines to return a data table for given SQL. That routine was this:
Public Function MyRst(strSQL As String) As DataTable
Dim rstData As New DataTable
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
Return rstData
End Function