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.
Related
I have a Repeater of checkboxes bound in code-behind:
<asp:Repeater runat="server" ID="rptOpenJobs" OnItemDataBound="rptOpenJobs_ItemDataBound">
<ItemTemplate>
<asp:CheckBoxList ID="lstOpen" runat="server"></asp:CheckBoxList>
</ContentTemplate>
</asp:Repeater>
Code-behind (VB.Net):
Protected Sub rptOpenJobs_ItemDataBound(sender As Object, e As RepeaterItemEventArgs)
Dim jobsTable As New DataTable
Dim conn As String = "[hidden]" 'Connection String to retrieve data table values
If e.Item.ItemType.Equals(ListItemType.AlternatingItem) Or e.Item.ItemType.Equals(ListItemType.Item) Then
Dim cboxlist As CheckBoxList = e.Item.FindControl("lstOpen")
If cboxlist.Items.Count = 0 Then
cboxlist.DataSource = jobsTable
cboxlist.DataTextField = "job_title"
cboxlist.DataValueField = "job_title"
cboxlist.DataBind()
End If
End If
End Sub
On form submission, the checked boxes do not stay checked. I've looked for solutions but haven't found any where the list is databound in code-behind.
I've tried adding an UpdatePanel around the repeater and around the CheckBoxList but the checked state still will not persist on form submission.
What does you page load event look like?
You ONLY load things up the first time in the If IsPostBack = False code stub.
99% if not 100% of your pages will ahve that code block. For me, comming from say Access, VB6, vb.net? Well a form loads, and we have the form load event.
but, any old button click on that page ALSO triggers a post back, and the on load event will run EVERY time (and then the button click or whatever event code will run).
So, all web pages look like this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
' the REAL first time load event!!!
LoadGrid()
End If
End Sub
Sub LoadGrid()
Using cmdSQL As New SqlCommand("SELECT ID, FirstName, LastName, HotelName, City from tblHotels",
New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
GridView1.DataSource = cmdSQL.ExecuteReader
GridView1.DataBind()
End Using
End Sub
So note how we have that first page load event - we load up a grid. But if we do NOT put that code inside of of the IsPostBack = False part, then our setup code and our load code will run every time on a full page post back.
Your check boxes as you have should persist for you, and should survive a page post back.
I don't see where (how) you persisted the jobs table, but ONCE the repeater is loaded, they should survive a post back. I mean, the data bound event only triggers if you are re-binding the repeater. but, if you are say due to adding new rows or some such, and you do trigger (need/want) a databind event again, then that jobsTable does need to exist and be persisted if you do re-bind the repeater.
So, in your code, you have on page load, we load up the Repeater. Above code would be the same, eg this:
And since the table is used OVER and OVER for each item data bound event, then we should NOT re-pull the table each time in the item data bound event. We should setup (load) that table one time in our LoadGrid routine.
So, at the page level class, we will declarer a table variable scoped to the form/page level. This will persist long enough during each item bind event for the repeater to fill out the check box list.
We assume that you have a data source for hte repeter - it will repeat many times. And for EACH repeater, we have a checkbox list that ALSO has a set of values that we want to fill from the check box list of choices.
It is NOT 100% clear if each new check box list is to be driven from ONE table, and each repeated row of course does have a value from the table for each row of the repeating list that represents the chosen check box value.
Or, is the list of check box values for each repeated item different? This issue has to be cleared up.
Clear this last issue up for me, and I post more code as to how this can work.
Sub LoadGrid()
Using cmdSQL As New SqlCommand("SELECT ID, FirstName, LastName, HotelName, City from tblHotels",
New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
rptOpenJobs.DataSource = cmdSQL.ExecuteReader
rptOpenJobs.DataBind()
End Using
End Sub
I have a user control that creates a grid view of database records. Each record has a checkbox for deleting the record.
My problem is that the the page_load event builds the grid view, then the delete button even fires. The deleteButton_click event is looping over the gridview looking for checked boxes but never finds any because the 'page_load' event just gave me a clean gridview. What is the best way to check for checked boxes before the grid view is re-built? Or can I get the checked values without looking at the grid view?
Protected Sub Page_Load(...) Handles Me.Load
'db calls and other code
gv.DataBind()
End Sub
Protected Sub btnDelAtt_Click(...) Handles btnDelAtt.Click
For Each grdRow As GridViewRow In gvFileViewer.Row
Dim chkBox As CheckBox = CType(grdRow.FindControl("cbItem"), CheckBox)
If chkBox.Checked = True Then 'this is always false thanks to page_load
'code that does not run
end if
next
end sub
As mentioned in the comments, adding !IsPostBack should do it.
You only need to load the grid from the database in the initial call, you don't need to get the data again when post back occurs. You will need to rebind the grid once the delete is over.
Protected Sub Page_Load(...) Handles Me.Load
If(!Page.IsPostBack)
'db calls and other code
gv.DataBind()
End Sub
Protected Sub btnDelAtt_Click(...) Handles btnDelAtt.Click
For Each grdRow As GridViewRow In gvFileViewer.Row
Dim chkBox As CheckBox = CType(grdRow.FindControl("cbItem"), CheckBox)
//Delete your record
end if
next
//Rebind grid
end sub
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 need to add a confirm delete action to a grid. the problem is the way the "Delete" link is rendered.
my grid is built in code behind in vb.net.
i have this
colDelete.AllowDelete = True
colDelete.Width = "100"
AddHandler CType(gridSavedForLater, Grid).DeleteCommand, AddressOf dgDeleteSelectedIncident
and the sub is the following
Sub dgDeleteSelectedIncident(ByVal sender As Object, ByVal e As GridRecordEventArgs)
Dim message As String = "Are you sure you want to delete this incident?"
Dim caption As String = "Confirm Delete"
Dim result = System.Windows.Forms.MessageBox.Show(message, caption, Windows.Forms.MessageBoxButtons.OKCancel, Windows.Forms.MessageBoxIcon.Warning)
'If (result = Windows.Forms.DialogResult.Cancel) Then
'Else
' MessageBox("Are you sure you want to delete this incident?")
'Get the VehicleId of the row whose Delete button was clicked
'Dim SelectedIncidentId As String = e.Record("IncidentId")
''Delete the record from the database
'objIncident = New Incidents(SelectedIncidentId, Session("userFullName"))
'objIncident.DeleteIncident()
''Rebind the DataGrid
LoadSavedForLater()
'' End If
End Sub
i need to add a javascript confirm dialog when this sub is called. i can do it with a windows form messagebox but that does not work on the server.
pleae help
joe
You cannot show a MessageBox in ASP.NET since it would be shown on the server. So you need a javascript confirm onclick of the delete button. Therefor you don't need to postback to the server first. You can attach the script on the initial load of the GridView.
A good place would be in RowDataBound of the GridView:
Private Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
Select Case e.Row.RowType
Case DataControlRowType.DataRow
' if it's a custom button in a TemplateField '
Dim BtnDelete = DirectCast(e.Row.FindControl("BtnDelete"), Button)
BtnDelete.OnClientClick = "return confirm('Are you certain you want to delete?');"
' if it's an autogenerated delete-LinkButton: '
Dim LnkBtnDelete As LinkButton = DirectCast(e.Row.Cells(0).Controls(0), LinkButton)
LnkBtnDelete.OnClientClick = "return confirm('Are you certain you want to delete?');"
End Select
End Sub
As an alternative, a common method of notifying users in a web page of a status change (save, delete, update, etc.) is having an update element in your HTML. Basically, a label (or whatever) that you'll set with updates to the user.
"Your changes have been successfully saved." or "An error was encountered when trying to save your update.", for example. You can set the color red for an error or whatever your programming heart desires, stylistically.
I kind of like this approach as a pop-up always feels more like a WinForm thing to me. Either works, so I just thought I'd suggest another approach.
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