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
Related
To explain my situation...
I am filling a listbox from a mysql table liek this
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim cmdtext = "SELECT * FROM avail_workouts"
Using conn = New MySqlConnection(connString)
Using cmd = New MySqlCommand(cmdtext, conn)
conn.Open()
reader = cmd.ExecuteReader()
While reader.Read()
ListBox1.Items.Add(reader("workout"))
End While
End Using
End Using
End Sub
I then select one of the items on the listbox and click on a button (that will do something with the value selected from the listbox) that does nothing for now. That's when I get this error
Invalid postback or callback argument.
Event validation is enabled using <pages enableEventValidation="true"/>
in configuration or <%# Page EnableEventValidation="true" %> in a page.
For security purposes, this feature verifies that
arguments to postback or callback events originate
from the server control that originally rendered them.
If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation
method in order to register the postback or callback data for validation.
I tried using
EnableEventValidation="false"
This seemed to work, until I tried to use the selected value in the listbox. It seems to forget the value that is selected when I click on the button. So, how can I simply fill up a listbox, select a row in the listbox, and click a button where the selected value will be used without getting this error?
Thanks in advance!
include this lines...
If Not IsPostBack
//your code
End If
I have two email fields, one a text field (index 15), the other a mailto: hyperlink (index 16), both in a gridview. (And yes, I know identifying via index isn't the best way to go -- just trying to make it work at this point).
When not editing, I need to show only the hyperlink field (making it available for the user to click on). When editing, I need to show only the text field, so they can modify the value.
I've got everything working as needed except that both fields display when the grid is initially shown. If I try to hide the text field in any of the normal ways (hiding cells on RowDataBound or hiding the column upon declaration), then it doesn't show up when editing.
Here's what I'm doing so far. The RowEditing event has the following code:
GridView1.Columns(16).Visible = False
GridView1.Columns(15).Visible = True
The RowCancelingEdit event has the opposite logic, toggling visibility on both fields. And finally the RowUpdating event has the following, which turns the hyperlink display back on:
GridView1.Columns(16).Visible = True
I'm relatively new to ASP.NET, so I definitely don't know all of the constructs available.
How can I hide the text field upon normal grid display, but still have the field available to show when in edit mode?
Try to RowCommand Event and set Edit button CommandName="name"
If e.CommandName = "name" Then
Dim row As GridViewRow = DirectCast(DirectCast(e.CommandSource, LinkButton).NamingContainer, GridViewRow)
Dim lblwwwhid = CType(row.FindControl("txtwwwhid"), Label)
lblwwwhid .visible =false
End if
It dawned on me that I could simply show/hide columns upon the initial databind (which works), as such:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
DataBind()
GridView1.Columns(16).Visible = True
GridView1.Columns(15).Visible = False
End If
End Sub
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.
The Repeater control in the following test case contains two runat="server" DIVs. Each one of them gets a TextBox appened to them through the ItemCreated event of the Repeater. Both of the have AutoPostBack=True, and TextChanged event wired to txt_TextChanged. However, only the TextBox from the first level properly points to the event on the postBack of the page. The second level TextBox also causes the postBack to occur, but its value does not persist in the VIEWSTATE as well as the event does not fire.
Here's a direct link to the test case in a .zip file (uploaded to my personal website), as well as all the code needed. The project is built in VS2010 using .NET Framework 4, but the problem also exists in 1.1, 2, and 3.5.
Anybody has any ideas on what is wrong and how to make this work?
ASPX
<asp:Repeater ID="rep" runat="server">
<ItemTemplate>
<!-- first level works -->
<div id="divOutside" runat="server">
<!-- second level doesn't work -->
<div id="divInside" runat="server"></div>
</div>
</ItemTemplate>
</asp:Repeater>
Code-Behind
Public Class WebForm1
Inherits System.Web.UI.Page
Private Sub WebForm1_Init(sender As Object, e As System.EventArgs) Handles Me.Init
If Not IsPostBack Then
Dim Table As New DataTable()
Table.Columns.Add("Column1")
Dim Row As DataRow = Table.NewRow()
Row("Column1") = ""
Table.Rows.Add(Row)
rep.DataSource = Table
rep.DataBind()
End If
End Sub
Private Sub repTest_ItemCreated(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rep.ItemCreated
' outside
Dim divOutside As HtmlGenericControl = DirectCast(e.Item.FindControl("divOutside"), HtmlGenericControl)
Dim txtInput As New TextBox
With txtInput
.ID = "txtInputOutside"
.AutoPostBack = True
.Text = "Event gets called, value persists accross postBack."
.Width = 400
End With
AddHandler txtInput.TextChanged, AddressOf txt_TextChanged
divOutside.Controls.Add(txtInput)
' inside
Dim divInside As HtmlGenericControl = DirectCast(e.Item.FindControl("divInside"), HtmlGenericControl)
txtInput = New TextBox
With txtInput
.ID = "txtInputInside"
.AutoPostBack = True
.Text = "Event NOT called, value is lost during postBack."
.Width = 400
End With
AddHandler txtInput.TextChanged, AddressOf txt_TextChanged
divInside.Controls.Add(txtInput)
End Sub
Protected Sub txt_TextChanged(sender As Object, e As EventArgs)
End Sub
End Class
Is there any reason why the textboxes have to be added to the divs dynamically? why not just put them in the aspx page with the repeater then on itemdatabound enable/disable or do whatever you need to do. That should work fine.
By the way, if you were to use panels instead of divs your on the fly approach will work.
Here's a link to Microsoft Connect, where I reported this is an official bug:
https://connect.microsoft.com/VisualStudio/feedback/details/652655/asp-net-bug-in-event-linking-of-2nd-level-dynamic-controls
It contains 2 PARTIAL workarounds that work in the uploaded files section, if anybody is interested or encounters the same problem, as well as details to what I found in the Workarounds tab.
To keep it short, it is the order of getting references to the containers and the order the TextBoxes are appended to their appropriate containers which either causes the issue or works as expected.
But, not to forget the most important point, the only reason the first-level TextBox is there in the first place is to showcase what I want as functionality. If the first-level TextBox does not get appended at all, then both workarounds fail to provide any sort of fix. Please keep that in mind when reviewing that problem - finding a workaround that revolves around changing the order of the items is not an actual solution or a fully working workaround!
Thanks everyone for the input!
I have GridView control in my asp.net page with auto generated fields
there is only footer template is present under asp:TemplateField.
I can bind this gridview with any of databae table as depend on user
selection. Now want to add new record in database so I have added text
boxes on footer template cells at runtime depend on number of columns
on table. But when I accessing these text boxes from footer template
on gridview_RowCommand event its not retriving textbox control.
this is the code:
SGridView.ShowFooter = True
For i As Integer = 0 To ctrList.Count
Dim ctr As Control = CType(ctrList.Item(i), Control)
SGridView.FooterRow.Cells(i + 1).Controls.Add(ctr)
Next
the ctrList contain Controls textBox, checkbox dropdowlist ect.
there is all ok
but when i wont to get the text or value or checked value of controls i can't cast the controls in rowcommand event
Here is the code:
If e.CommandName = "Add" Then
Dim ctrList As ControlCollection = SGridView.FooterRow.Controls
For Each ctr As Control In ctrList
If TypeOf ctr Is TextBox Then
Dim name As TextBox = CType(ctr, TextBox)
Dim val As String = name.Text
End If
Next
End If
this excample is for the textBox control.
Plese suggest me how can I get footer control textboxes. So that I can
save data in database.
When you are dealing with Dynamic controls you have to keep a close eye on the .net page lifecycle.
Control data is bound in the Load event, so your not able to access postback data in that event when your doing your conrol generation in the Load event too. I usualy try to create dynamic controls in the Init of the page, and do any values processing on the LoadComplete or PreRender event so I can make sure they have recieved their values from the postback before you try to read them.
Take a look at the full description of the ASP.NET page lifecycle events and whats going on. This should help you navigate the creation and use of Dynamic generated controls.
Try to create your Controls in the Grdiview's RowCreated Event which will be raised on every Postback.
Private Sub Grid1_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles Grid1.RowCreated
Select Case e.Row.RowType
Case DataControlRowType.Footer
'add controls to row
End Select
End Sub