I have an asp.net Visual Basic web site, and I am using a stored procedure to get values to populate a drop-down list.
However, I have two issues. If I put the method to fill the drop-down list within my If Not IsPostBack statement in the page load event, then the whole list is filled with items saying 'System.Data.DataViewRow' instead of the actual values. If I put it outside this 'if' statement but still in my page load event, I get the correct values, but no matter what I select, when I leave the drop-down it reverts back to the top item instead of the selected item.
What am I doing wrong??
Edit: I have now added the DataTextField as suggested by Nic and put the method inside my 'If Not IsPostBack' event as suggested by Lee Bailey. However, my drop-down is still showing all values as 'System.Data.DataViewRow' so I don't know if Lee's solution has worked or not! Any other ideas on the issue of showing the values! I have updated my code below to reflect the changes.
The visual basic:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
bodyPanel.Visible = False
drpRegion_fill()
End If
End Sub
Protected Sub drpRegion_fill()
Dim sqlConn As SqlConnection
sqlConn = New SqlConnection
sqlConn.ConnectionString = ConfigurationManager.ConnectionStrings("ConnString").ConnectionString
Dim drpRegionCmd As SqlCommand
drpRegionCmd = New SqlCommand("getRegionName", sqlConn)
drpRegionCmd.CommandType = CommandType.StoredProcedure
Dim drpRegionAdp As SqlDataAdapter
drpRegionAdp = New SqlDataAdapter(drpRegionCmd)
Dim drpRegionDs As DataSet
drpRegionDs = New DataSet
sqlConn.Open()
drpRegionAdp.Fill(drpRegionDs)
With drpRegion
.DataSource = drpRegionDs
.DataBind()
.DataValueField = "regionName"
.DataTextField = "regionName"
.SelectedIndex = 0
End With
sqlConn.Close()
End Sub
The markup:
<asp:Panel ID="panelRegion" runat="server" Height="160px" Width="71%" CssClass="inlineBlock">
<h2>Region:</h2>
<asp:dropDownList runat="server" AutoPostBack="true" ID="drpRegion" />
</asp:Panel>
The SQL procedure returns a two-column dataset with 'regionID' as column 1, and 'regionName' as column2.
I've spent about two days on this now, trying various things and reading all the books I can! I have never had this issue in C# when I have performed the same operation and I cannot for the life of me think what I've missed in the VB...
It does not look as though you are setting the DataTextField property of your DropDownList:
With drpRegion
.DataSource = drpRegionDs
.DataValueField = "regionName"
.DataTextField = "fieldToDisplayAsText"
.SelectedIndex = 0
.DataBind()
End With
source:
MSDN DataTextField
It's reverting back to the original value because you are re-binding the values to the dropdown after a postback. Changing the selected item is triggering a postback because you have the AutoPostBack property set to true. I would call drpRegion_fill() only if it's not a postback. Setting the DataTextField as Ric mentioned should solve the problem regarding 'System.Data.DataViewRow'
Related
I have a gridview which has a List (Of MyObject) as its datasource.
gv.DataSource = MyListObject
gv.Databind()
Under a templatefield i have a button configured to delete a record from MyListObject and then rebind it. To add a record i have the below code
Protected Sub btnAddRecord_Click(sender As Object, e As EventArgs) Handles btnAddRecord.Click
Dim Customer As New Customer
With Customer
.Name = txtName.Text
.Surname = txtSurname.Text
.....
.ID += MyListObject.Count
End With
MyListObject.Add(Customer)
gv.DataSource = MyListObject
gv.DataBind()
End Sub
This works fine, but then i need to allow the user to delete a record if need be:
Private Sub gv_RowCommand(sender As Object, e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles gv.RowCommand
If e.CommandName = "Delete" Then
MyListObject.RemoveAt(e.CommandArgument)
gv.DataSource = Nothing
gv.DataBind()
gv.DataSource = MyObjectList
gv.DataBind()
upnl.UpdateMode = UpdatePanelUpdateMode.Conditional
upnl.Update()
End If
End Sub
When i click the button it deletes the record but doesnt refresh the data. By that i mean when the record is added i am assigning the ID as a row ID and then use that ID to remove the record. Since the List and Gridview values are now out of sync i set the datasource to nothing and rebind it in order that i was going to have the values reset and the ID would be the correct one - but this doesnt works as i expected.
Could anyone advise where im going wrong and how to correct this problem?
Is gridview in the updatepanel? If yes, that panel should also be refreshed.
I added CommandArgument='<%# Container.DataItemIndex %>' which resolved the issue as i was then deleting the row the user clicked against.
Just as a side note, I'd probably handle what get's updated when on the client side using the ajax script manager rather than doing it in the code behind. Saves headaches. The above might be updating the update panel correctly, but the ajax plumbing may not be there on the client side.
Good afternoon people have been trying to fill a dropdown using a sql command, until so good, when I click on the dropdown it shows all the items, but when I try to click on an item in the dropdown it always returns the first item in the dropdown .... follows the codes, what i want to do is get the selected value and item from the dropdown and save it on a label for future use.
I appreciate all the support possible,
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
utilizador.Text = Me.Context.User.Identity.Name
If (Not Page.IsPostBack) Then
escolhePerfil()
End If
'DropDownPerfil.DataBind()
lbperfil2.Text = DropDownPerfil.SelectedItem.Text
lbnome.Text = DropDownPerfil.SelectedValue
End Sub
Function escolhePerfil() As Boolean
Dim connstring As String = "Data Source=10.2.24.17;Persist Security Info=True;User ID=sa;Password=Pr0dUn1C0$qL;database=ePrimavera"
Dim SQLData As New System.Data.SqlClient.SqlConnection(connstring)
Dim cmdSelect As New System.Data.SqlClient.SqlCommand("SELECT u.WindowsUser,u.Email ,g.Description, u.Login FROM [ePrimavera].[dbo].[PLT_Users] as u,[ePrimavera].[dbo].[PLT_UserGroups] as ug, [ePrimavera].[dbo].[PLT_Groups] as g where u.ID = ug.UserID And ug.GroupID = g.ID and u.WindowsUser like 'bancounico\" & utilizador.Text & "'", SQLData)
SQLData.Open()
Dim dtrReader As System.Data.SqlClient.SqlDataReader = cmdSelect.ExecuteReader()
If dtrReader.HasRows Then
DropDownPerfil.DataValueField = "Login"
DropDownPerfil.DataTextField = "Description"
DropDownPerfil.DataSource = dtrReader
DropDownPerfil.DataBind()
End If
SQLData.Close()
Return True
End Function
.aspx
<asp:DropDownList ID="DropDownPerfil" runat="server"
Height="16px" Width="202px" CssClass="DropBorderColor">
</asp:DropDownList>
try the following code:
Protected Sub DropDownPerfil_SelectedIndexChanged(sender As Object, e As EventArgs)
lbperfil2.Text = DropDownPerfil.SelectedItem.Text
lbnome.Text = DropDownPerfil.SelectedValue
End Sub
The problem is that you are trying to get the value "too early". The value is not valid in the Page_Load, since the control's OnLoad event fired after the Page's OnLoad (Page_Load) event.
The way, what the others wrote the correct, since the Event handlig section (inclueding control's onchanged event) will process after the Load section.
For more details check the offical ASP.NET life cycle site in the MSDN
The likely reason is that some (if not all) the values you are assigning to the DropDownList for Login are occur more than once.
When you then select an item in the DDL, if the value of that item occurs more than once, the selected index will highlight the first instance. To test this, comment out DropDownPerfil.DataValueField = "Login"
I am sure upon selection, it will highlight the correct item you intended on selecting.
I've got a grid view. I want it to say "you have nothing to show" if there are no details.
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
If GridView1.Rows.Count = 0 Then
Lblemptygridview.Text = "you do no details to show"
Elseif e.Row.RowType = DataControlRowType.DataRow then
Dim datakey As String = GridView1.DataKeys(e.Row.RowIndex).Value.ToString()
End If
End Sub
However; it seems to be working backwards and showing the message when there is data to display in the gird view and continues to be a blank page when there is not data to display in the grid view.
I've tried a variety of combinations with the below IF statement below but no success.
Instead, use the EmptyDataTemplate:
<emptydatatemplate>
No Data Found.
</emptydatatemplate>
This is more of an addendum to Icarus's answer, adding a bit of context as to why your solution does not work. (For educational purposes).
RowDataBound is called when a Row is bound to the gridview. This basically means that this is called for every row in the grid view.
Now, the reason why your solution doesn't work, is that if your GridView simply has nothing in it, RowDataBound will not be called.
The reason why you're getting 'No Data Found' when you DO have data, is because the first time the if statement runs when loading a GridView, the GridView (at the time of execution) has no Rows, which results in your if statement being true.
Just something to keep in mind.
Just a suggestion..
Instead of showing "you have nothing to show" in a gridview which looks outdated, why don't you make it fancy??
You can do
Dim dt As DataTable = getDatatable()
If Not dt Is Nothing AndAlso dt.Rows.Count > 0 Then
GridView1.datasource = dt
GridView1.databind()
div.style.add("display", "none")
Else
GridView1.visible = False
'Add some fancy style here to show no record
div.style.add("display", "block")
End If
thanks
In my ListView I have an ItemTemplate and EditItemTemplate which look something like this, respectively.
------->
When I click the "Edit" button, and it switches to the EditItemTemplate view on the right, I want to prefill the Textbox and select the corresponding option in the DropDownList. How can I do this?
Before you say to use something like the following, please know that I've already explored every possible variation I can think of. Sorry to be so demanding, but please be prepared to walk me through this one if you answer. ^.^ I've been stuck on this issue for literally months :(
Dim lv As ListView = DirectCast(sender, ListView) 'sender is the ListView on the ItemCommand event
Dim ddl As DropDownList = DirectCast(lv.Items(0).FindControl("NewProductName_ddl"), DropDownList)
Dim tb As TextBox = DirectCast(lv.Items(0).FindControl("NewProductName_tb"), TextBox)
UPDATE - RAWR!!
Oh my freaking goodness, SO CLOSE, but no cigar. The following code worked for prefilling when only one item was in the ListView, but when more than one items exist, it throws a NullReferenceException :(
'PROBLEM WAS HERE: Compare to the working code in my answer.
Protected Sub NewProduct_ItemDataBound(ByVal sender As ListView, ByVal e As ListViewItemEventArgs) Handles NewProduct.ItemDataBound
If sender.EditIndex > -1 Then
Dim ddl As DropDownList = DirectCast(e.Item.FindControl("NewProductName_ddl"), DropDownList)
Dim tb As TextBox = DirectCast(e.Item.FindControl("NewProductName_cb"), TextBox)
ddl.Items.FindByValue(sender.DataKeys(sender.EditIndex)("ID").ToString).Selected = True 'Prefills the DropDownList
tb.Text = sender.DataKeys(sender.EditIndex)("Product").ToString 'Prefills the TextBox
End If
End Sub
EUREKA!!
I am elated beyond imagination!! All caps, nor bold do justice to how happy I am right now :)
First I wanna give props to this question which got me pointed in the right direction. Now onto the answer, which is the most ideal variation I have found of the answer provided in the above link:
The ItemDataBound event is the key, but it's important to note that this event will fire for each item that exists in your ListView and for that reason, you must be careful in your approach. Here are two options that worked equally well for me.
Option 1 - Most elegant; only runs FindControl on the item in question rather than all items.
Protected Sub NewProduct_ItemDataBound(ByVal sender As ListView, ByVal e As ListViewItemEventArgs) Handles NewProduct.ItemDataBound
Dim i As Integer = sender.EditIndex
If i = e.Item.DataItemIndex Then
Dim ddl As DropDownList = DirectCast(e.Item.FindControl("NewProductName_ddl"), DropDownList)
Dim tb As TextBox = DirectCast(e.Item.FindControl("NewProductName_cb"), TextBox)
ddl.Items.FindByValue(sender.DataKeys(i)("ID").ToString).Selected = True 'Prefills the DropDownList
tb.Text = sender.DataKeys(i)("Product").ToString 'Prefills the TextBox
End If
End Sub
Option 2 - Based on the referenced question, but with a crucial check to ensure non-null object.
Protected Sub NewProduct_ItemDataBound(ByVal sender As ListView, ByVal e As ListViewItemEventArgs) Handles NewProduct.ItemDataBound
Dim i As Integer = sender.EditIndex
If i > -1 Then
Dim ddl As DropDownList = DirectCast(e.Item.FindControl("NewProductName_ddl"), DropDownList)
Dim tb As TextBox = DirectCast(e.Item.FindControl("NewProductName_cb"), TextBox)
If Not IsNothing(ddl) Then
ddl.Items.FindByValue(sender.DataKeys(i)("ID").ToString).Selected = True 'Prefills the DropDownList
End If
If Not IsNothing(tb) Then
tb.Text = sender.DataKeys(i)("Product").ToString 'Prefills the TextBox
End If
End If
End Sub
I may make improvements to this answer later, but this did the trick for me. :)
Great post! I had the same problem and you saved me hours of trial and error. Just wanted to point out that when using your first option with .NET Framework 3.5 or lower, DataItemIndex isn't available. To work around it you can replace
If i = e.Item.DataItemIndex Then
With
If i = DirectCast(e.Item, IDataItemContainer).DataItemIndex Then
I'm usually a PHP guy but got stuck doing a project in vb.net.
I have a query (sqldatasource) that returns a single value (the last update date).
I want to use a label to say something like "Last updated: " < Label = (returned value) >
In PHP this would be simple. In vb.net, all I can find are endless badly written code behinds showing how you'd execute the query onLoad then bind it to the label.
Is this really the only way to do this? It seems like a ridiculously simple problem to have such a long solution. I have used a datagrid control to just bind the query result directly, but it prints the column name as well as the date, so it's not ideal.
Any ideas?
In your Page_Load method, run your query. On your page.aspx, you have a form control, lets call it label1. Set label1.text = queryResult.
Sub Page_Load()
dim myConnection as new data.sqlclient.sqlconnection
dim myCommand as new data.sqlclient.sqlcommand
dim sqlReader as data.sqlclient.sqldatareader
myConnection.connectionString = 'enter your connection string details'
myConnection.Open()
myCommand = New SqlCommand("Select lastUpdated from yourTable", myConnection)
sqlReader = myCommand.ExecuteReader()
if sqlReader.hasRows then
sqlReader.read()
label1.text = Format("MM/dd/yyyy", sqlReader("lastUpdated"))
end if
End Sub
And your page.aspx (somewhere)
<asp:label id="Label1" runat="server" />
PS - I may be off on the format function above, been awhile.
EDIT based on user comment:
Well, for what you are doing, I wouldn't really recommend a SQLDataSource as it is really meant to be bound to a control such as a gridview or repeater. However, if you want to use the SQLDataSource, you will need to bind to a DataView in your code-behind. From there, you can access each row (you should only have one) and column by name.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim dv As New Data.DataView
'use the id of your SqlDataSource below'
dv = SqlDataSource1.Select(DataSourceSelectArguments.Empty)
Label1.Text = dv.Table.Rows(0)("LastUpdated")
End Sub
TO use a connection string from the web.config:
Web.Config File:
<appSettings>
<add key="strConnectionString" value="Data Source=192.168.0.55;Database=Times;User ID=sa;PassWord=sa"/>
</appSettings>
Code Behind:
Dim sqlConn as new data.sqlClient.SqlConnection()
sqlConn.ConnectionString=ConfigurationManager.ConnectionStrings("strConnectionString").ConnectionString
sqlConn.Open()