OnCheckChanged not Firing when Unchecked - asp.net

I've googled this topic as much as i could, ive found similar topics around and even on stackoverflow but none were able to resolve my issue. I have a nested gridview bound to a sqldatasource that populates a few fields as well as a checkbox field from a 'bits' field in the database. The checkboxes populate correctly from the database (checked vs. unchecked) but my 'OnCheckedChanged' event only fires when i check a checkbox but does NOT fire when it is unchecked, the page just goes through its post back. I have 'EnableViewState' set to true on the master page, local page, and on the control as well as auto post back. What i need to do is update the DB with the new value of the checkbox (checked vs unchecked) and reload. Please let me know if anyone has suggestions.
Protected Sub Gridview3_OnCheckedChanged(Sender As Object, e As EventArgs)
Dim checkbox As CheckBox = TryCast(Sender, CheckBox)
Dim gridview3 As GridView = checkbox.Parent.Parent.Parent.Parent
Dim row As GridViewRow = checkbox.Parent.Parent
sql_insert(String.Format("UPDATE [STOREIT2-PORTAL].dbo.AA5VOLUMES SET PROTECTED = '{0}' WHERE GUID = '{1}' AND AGENTID = '{2}'", checkbox.Checked, gridview3.DataKeys(row.RowIndex).Values("GUID").ToString, gridview3.DataKeys(row.RowIndex).Values("AgentID").ToString))
End Sub
<asp:GridView ID="Gridview3" EnableViewState="true" runat="server" AutoGenerateColumns="False" DataKeyNames="AgentID,GUID" OnRowDataBound="GridView3_OnRowDataBound" RowStyle-CssClass ="row" AlternatingRowStyle-CssClass="altrow" RowStyle-HorizontalAlign="Center" CssClass="gvmain"> <AlternatingRowStyle CssClass="altrow"></AlternatingRowStyle>
<columns>
<asp:BoundField DataField="AgentID" HeaderText="AgentID" SortExpression="AgentID" visible="false"/>
<asp:BoundField DataField="GUID" HeaderText="GUID" SortExpression="GUID" visible="false"/>
<asp:BoundField DataField="VolumeName" HeaderText="VolumeName" SortExpression="VolumeName" readonly="true"/>
<asp:BoundField DataField="Label" HeaderText="Label" SortExpression="Label" nulldisplaytext="<i>{No Label}</i>" readonly="true"/>
<asp:BoundField DataField="BaseCount" HeaderText="BaseCount" SortExpression="BaseCount" nulldisplaytext="<i>{No Base Images}</i>" readonly="true"/>
<asp:BoundField DataField="TimeStamp" HeaderText="TimeStamp" SortExpression="TimeStamp" nulldisplaytext="<i>{Volume has no recent snapshots}</i>" readonly="true"/>
<asp:TemplateField headertext="Protected">
<ItemTemplate>
<asp:CheckBox ID="Protected" EnableViewState="true" runat="server" autopostback="true" checked='<%# Eval("Protected")%>' OnCheckedChanged="Gridview3_OnCheckedChanged"/>
</ItemTemplate>
</asp:TemplateField>
</columns>
</asp:GridView>

I'm noticing your code does not have the 'Handles Clause' Maybe this is causing the problem you mention. . .
Handles CheckBox1.CheckedChanged

Related

How do I make a read only cell editable in a gridview control in asp using vb?

Hi me again with another question.
I'm using VS2019 and VB on an aspx page. I have a gridview that has Edit enabled.
enter image description here
When a user clicks the EDIT link Progress % and Comments become editable.
What I want to do is make the Goal be editable if Approved is set to No.
How can I do this?
<asp:GridView ID="grdgoals" runat="server" AutoGenerateColumns="False" DataSourceID="DS1" Height="225px" Width="1001px" BorderColor="#003960" BorderStyle="Solid" BorderWidth="1px" DataKeyNames="goalid" EmptyDataText="No goals found." Font-Bold="True" Font-Names="Calibri" Font-Overline="False" Font-Size="Medium" Font-Strikeout="False" ForeColor="#00AD86" ShowHeaderWhenEmpty="True" AllowSorting="True" style="margin-right: 21px">
<Columns>
<asp:BoundField DataField="goalid" HeaderText="goalid" ReadOnly="True" SortExpression="goalid" Visible="False" />
<asp:CommandField EditText="EDIT" ShowEditButton="True" ShowHeader="True">
<HeaderStyle BorderColor="#003960" />
<ItemStyle Font-Names="Calibri" Font-Underline="True" ForeColor="#006EAA" HorizontalAlign="Center" BorderColor="#003960" Width="20px" />
</asp:CommandField>
<asp:BoundField DataField="goaltext" HeaderText="Goal" SortExpression="goaltext" ReadOnly="True" >
<HeaderStyle BorderColor="#003960" />
<ItemStyle BorderColor="#003960" Width="250px" />
</asp:BoundField>
<asp:BoundField ConvertEmptyStringToNull="True" DataField="type" HeaderText="Type" ReadOnly="True" >
<ItemStyle Width="70px" />
</asp:BoundField>
<asp:BoundField DataField="progress" HeaderText="Progress %" SortExpression="progress" >
<HeaderStyle BorderColor="#003960" />
<ItemStyle HorizontalAlign="Center" BorderColor="#003960" VerticalAlign="Middle" Width="20px" />
</asp:BoundField>
<asp:BoundField DataField="comments" HeaderText="Comments" SortExpression="comments" ItemStyle-Wrap="true">
<ControlStyle Height="400px" Width="240px" />
<HeaderStyle BorderColor="#003960" />
<ItemStyle BorderColor="#003960" Width="250px" HorizontalAlign="Left" VerticalAlign="Middle" />
</asp:BoundField>
<asp:BoundField DataField="approved" HeaderText="Approved" ReadOnly="True" SortExpression="approved" >
<ItemStyle HorizontalAlign="Center" Width="40px" />
</asp:BoundField>
</Columns>
<EditRowStyle HorizontalAlign="Left" VerticalAlign="Top" />
<HeaderStyle ForeColor="#006EAA" />
</asp:GridView>
I have searched online looking for answer but haven't found anything.
Ok, so how much extra code is it to simple drop in a "plain jane" button to click on and edit?
It not much!!!
You do have to bear the cost/time of building a form layout for the one row, but at the end of the day:
this tends to be "easy" for the users.
You can also then move the row delete button to that "form layout" area for editing one record. (this means you don't need a delete record button on the GV - not a huge deal, but that means users have to make a "bit more" effort to delete a row of data if that option is desired).
However, the "why" of having a detail edit layout?
You can now have MUCH more control over your logic (such as the rule to allow what to edit, change or even "enable" based on other values. And such code is clean easy server side code.
And this allows far more code logic into the editing of that data. (required fields, formatting, all that stuff.
Best bonus feature?
Such a approach now ALSO allows adding of new records in a MUCH more user friendly way, since now the "edit" area you build ALSO can be used as the "add new" record area. (so, you save having to write separate code for edit and adding - the one solution does both). And this also means the end user has the "same" experience when editing existing, or adding new - it shortens the user learning curve.
Now, about the only downside?
Well, when starting out, those wizards can be a real gift horse. And I still after all these years often use the wizard(s) to create the GV.
however, I THEN clean it up a bit, and remove things from the page.
(such as removing the datasource on the page).
And the other tip?
If possbile, build a few "helper" routines. They can be used over and over.
For example, I became VERY tired of having to type in code with a row of data, and then "please fill out" those controls on the page with that data.
Then after done, we have to take that those controls, and send back to the database. We do this "over and over". And the code to do this is darn near the "same" over and over. So, then, why not write one sub routine that can do this for ANY page we work on!!!
So, here is a working approach.
for the GV, then the markup becomes rather clean - just some fields.
Say, like this markup:
<asp:GridView ID="GridView1" runat="server" Width="40%"
AutoGenerateColumns="False" DataKeyNames="ID"
CssClass="table table-hover table-striped" >
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit"
CssClass="btn myshadow"
OnClick="cmdEdit_Click"
/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Note a few things in above:
If we don't use width, or use 100%? The GV will expand to the WHOLE page - it is what we call "responsive".
I assume that you have bootstrap installed, and most projects do (by default).
The result is a "very" nice grid, and the fonts + spacing and layout is "tweaked" by bootstrap. The result is quite nice.
Code to load the GV is this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData()
End If
End Sub
Sub LoadData()
Dim strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName"
Dim cmdSQL As New SqlCommand(strSQL)
GridView1.DataSource = MyrstP(cmdSQL)
GridView1.DataBind()
End Sub
Note the "helper" routine MyrstP. I use this "over and over" everywhere.
(I'll post that at end of this post).
So, I removed the Sqldatasourc1 from the page. I find that you obtain/enjoy MUCH more control over the code. (but, if you don't have a helper routine, then setting up a query + connection and all that jazz? Then you might as well just stick with the wizard generated SqlDataSource on the page. But, you find over time that using code behind is a "less effort" choice, and one that gives you far more control (say to filter, or do other things).
And note the table hover (you get a "nice" row hover effect), and note the table-striped. That gives you a nice alternating row shade - and you do not need a messy "alternating" template.
So far? We have a VERY clean markup, and so far VERY little code has been written.
Now, not the button we dropped into the GV. That is a plan jane asp.net button. We don't need to use "speical" commands, "speical" code or anything. Just a good old fashioned button and button click.
However, do note that we have a click event for the button. Normally, I often just double click on a button, and then a code behind stub is created, and we are jumped to the code behind editor.
however, since the button is "nested" in a GV, then we can't double click on that button to create a event.
So, flip to markup. And in markup type in
OnClick=
WHEN you hit the "=", then intel-sense should pop up and gives you the option to create the event. (since we can't use double click on button to do this).
So, it looks like this:
And thus the code is for button click:
Protected Sub cmdEdit_Click(sender As Object, e As EventArgs)
Dim btn As Button = sender
Dim gRow As GridViewRow = btn.NamingContainer
Dim intPK As Integer = GridView1.DataKeys(gRow.RowIndex).Item("ID")
Dim cmdSQL = New SqlCommand("SELECT * FROM tblHotelsA WHERE ID = #ID")
cmdSQL.Parameters.Add("#ID", SqlDbType.Int).Value = intPK
Dim rstHotel As DataTable = MyrstP(cmdSQL)
ViewState("PKID") = intPK
fLoader(EditRecord, rstHotel.Rows(0))
GridView1.Visible = False ' Hide GV
EditRecord.Visible = True ' show edit area
End Sub
Again, note the small amount of code.
The button click thus:
we get GV row
we get GV row PK database ID (using datakeys feature)
we pull that data row into data table
we call the floader() routine that takes ONE row, fills out controls.
the resulting effect is thus this:
And our helper MyRstP routine is this:
Public Function MyrstP(cmdSQL As SqlCommand,
Optional cmdOnly As Boolean = False) As DataTable
Dim rstData As New DataTable
Using mycon As New SqlConnection(GetConstr)
Using (cmdSQL)
cmdSQL.Connection = mycon
mycon.Open()
If cmdOnly Then
cmdSQL.ExecuteNonQuery()
Else
rstData.Load(cmdSQL.ExecuteReader)
End If
End Using
End Using
Return rstData
End Function
I'll post more code from above (later this evening)., and say have some "conditional" code. Say if the hotel not active, we can't edit description.

Gridview is not updating inside of UpdatePanel

I understand that this is a very common issue, I have been reading documentation on it for days, and I am about to pull my hair out over this issue.
BACKGROUND
I have multiple Gridviews inside of an UpdatePanel. What is happening, is someone is importing an Excel spreadsheet, I am using OpenXML to shread the data and store it in a VB.NET datatable object. I then run all of that data through a custom validation (based on DB information) and then spit out the exceptions (errors) that occur into a Gridview depending on the exception. the max number is 4 Gridviews in one UpdatePanel (each Gridview has it's own functionality). There are two Gridviews that I am using a button to do an action using the data contained in the Gridview. Those two buttons are also located in the Update Panel, just underneath the corresponding Gridviews. Each Gridview is wrapped in an AJAX Collapsible Panel Extender.
Now, when the user clicks on the button, I have a click event in the code behind where I take the information and depending on the exception that occurred, Update or Insert the DB. I loop through the rows, and if no error occurs, I call the datatable.ImportRow and pass the current row to my "Ready" table. I use a ScriptManager.RegisterStartupScript in order to display an alert box letting them know if any errors occurred. Then, I rebind the exception table and the "Ready" table. I have tried just adding an AsyncPostbackTrigger, I have attempted simply calling udpMain.Update() in the code behind, and tried both options of setting the UpdatePanel's UpdateMode property to "Always" and "Conditional".
HTML
<asp:UpdatePanel ID="udpMain" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:Panel ID="pnlOwnershipDetailsHead" runat="server" Visible="false">
<div class="windHeader" style="cursor: pointer">
<asp:Label id="lblOwnershipDetails" runat="server">Ownership Exceptions</asp:Label>
<asp:ImageButton id="btnOwnershipHead" runat="server"/>
</div>
</asp:Panel>
<asp:Panel ID="pnlOwnershipDetailsBody" runat="server" Visible="false" CssClass="pnl">
<asp:GridView ID="gvOwnershipDetails" runat="server" CssClass="wind" CellPadding="5" AutoGenerateColumns="false">
<HeaderStyle CssClass="windHeader" />
<Columns>
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:BoundField DataField="Serial Number" HeaderText="Serial Number" />
<asp:BoundField DataField="Facility" HeaderText="Facility" />
<asp:BoundField DataField="Department" HeaderText="Department" />
<asp:BoundField DataField="EmpID" HeaderText="EmpID" />
<asp:BoundField DataField="Configuration" HeaderText="Config" />
<asp:BoundField DataField="Error" HeaderText="Errors" />
<asp:TemplateField>
<HeaderTemplate>
<asp:CheckBox ID="chkHeader" ToolTip="Select All" runat="server" onclick="changeAllCheckBoxes(this)" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkItem" runat="server" ToolTip="Select this item" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Button ID="btnOwnershipDetails" Text="Change Information" runat="server" CssClass="btn editBtn" />
<ajax:ConfirmButtonExtender ID="cbeOwnershipDetails" runat="server" TargetControlID="btnOwnershipDetails"
ConfirmText="Are you sure you would like to change the ownership information for the selected items?"
OnClientCancel="CancelClick" />
</asp:Panel>
</ContentTemplate>
<asp:UpdatePanel>
CODE BEHIND
Protected Sub btnOwnershipDetails_Click(sender As Object, e As System.EventArgs) Handles btnOwnershipDetails.Click
Dim importdata As New ImportData
Dim ownershipdt As Data.DataTable = Session("ownershipdt")
Dim finalimportdt As Data.DataTable = Session("finalimportdt")
Dim existsError As Boolean = False
For Each Row As Data.DataRow In ownershipdt.Rows
Dim i As Integer = 0
Dim cb As CheckBox = CType(gvOwnershipDetails.Rows(i).Cells(7).Controls(1), CheckBox)
If cb.Checked Then
If importdata.CheckEmpExists(Row("EmpID").ToString) And importdata.CheckSiteExists(Row("Facility").ToString) And importdata.CheckDeptExists(Row("Department").ToString) Then
importdata.UpdateDBOwnership(Row("Serial Number").ToString, ClientInfo.GetEmpID(Row("EmpID").ToString), ClientInfo.GetSiteID(Row("Facility").ToString), ClientInfo.GetDeptID(Row("Department").ToString), _
Row("Description").ToString, Row("Configuration").ToString, portalUser.EmployeeText)
finalimportdt.ImportRow(Row)
Else
existsError = True
End If
End If
i += 1
Next
If existsError = False Then 'Show alert box
ScriptManager.RegisterStartupScript(udpMain, udpMain.GetType(), "alert", "alert('You have changed the ownership information for the selected rows.')", True)
Else
ScriptManager.RegisterStartupScript(udpMain, udpMain.GetType(), "alert", "alert('There was an issue changing ownership to all of the selected rows.')", True)
End If
bindGV(gvOwnershipDetails, ownershipdt)
bindGV(gvImportDetails, finalimportdt)
'udpMain.Update()
Session("ownershipdt") = ownershipdt
Session("finalimportdt") = finalimportdt
btnEmail.Enabled = True
End Sub
Put your panel code between ContentTemplate under asp:UpdatePanel
<asp:UpdatePanel>
<ContentTemplate>
</ContentTemplate>
</asp:UpdatePanel>
Finally! I Have found the answer! https://sites.google.com/site/arlen4mysite/full-postback-for-templatef
Or a single line of code in the Page_Load() does the same thing
ScriptManager.GetCurrent(this).RegisterPostBackControl(btnOwnershipDetails);

Checkbox within Datagrid retaining checked value on postback in VB.NET but not C#

Hey there, I have a project in VB.NET which is working fine which essentially has a Datagrid that has a TemplateColumn included which is a column of Checkboxes. The code to declare the datagrid is here...
<asp:datagrid id="dgDates" OnItemCommand="gridEventHandler" BorderColor="Black" BorderWidth="1px"
CellPadding="3" runat="server" AutoGenerateColumns="False" HorizontalAlign="Left" AllowSorting="True"
OnSortCommand="SortData" OnItemDataBound="gridItemDataBound">
<HeaderStyle Font-Underline="True" Font-Bold="True" HorizontalAlign="Center" ForeColor="Black"
BackColor="#D4D0C8"></HeaderStyle>
<Columns>
<asp:BoundColumn DataField="strParameterName" SortExpression="strParameterName" HeaderText="Parameter Name"></asp:BoundColumn>
<asp:BoundColumn DataField="dtParameterValue" SortExpression="dtParameterValue" HeaderText="Parameter Value"></asp:BoundColumn>
<asp:TemplateColumn HeaderText="Constant" SortExpression="blnStatic" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:CheckBox ID="cbStaticRolling" Checked="False" Runat="server" AutoPostBack="true"></asp:CheckBox>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
as you can see the Checkbox has Autopostback="true" but there are other things on the page which produce postbacks as well.
My Page_load has this in it, being called on every load of the page, postbacks included...
Dim strGUID As String
strGUID = Session("strGUID")
dgDates.DataSource = SqlHelper.ExecuteDataset(ConfigurationManager.AppSettings(Web. [Global].CfgKeyConnStringADMIN), "dbo.spRptGetSchedulingDates", strGUID)
dgDates.DataBind()
intNumberOfDates = dgDates.Items().Count
as well my code behind has the following code for the gridItemDataBound
Protected Sub gridItemDataBound(ByVal sender As System.Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs)
'hide the intRptSchedulingDatesID for each row in the checkbox's content style variable
If (e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem) Then
CType(e.Item.FindControl("cbStaticRolling"), CheckBox).Style("Content") = CType(e.Item.DataItem, System.Data.DataRowView).Item("intRptSchedulingDatesID")
End If
End Sub
everything you see sbove is working perfectly fine...in the sense that when I click one of the checkboxes, the page_load fires, the gridItemDataBound fires on DataBind() and when all is done, the checkbox retains the value that the user clicked the checkbox.
With all this exact same code converted to C#....the events all fire in the same order, but the checkbox selected value always clears...any thoughts??
I'd say the problem is that you're are binding the grid on every postback (I can't explain the difference between VB and C#). This clears your selections. Why are you doing this?
You bind the grid on every page_load, this causes checkbox to be always the same.
Try to attach a checkedchange event on ItemDataBound and when event fires, store checkbox value on a session variable.
On ItemDataBound, check session variable and if its null, run this code, otherwise read checkbox's value from your session variable
And On Page_Load, if not IsPostBack (page is loading first time), set your session value to null

GridView's NewValues and OldValues empty in the OnRowUpdating event

I have the GridView below. I am binding to a custom datasource in the code behind. It gets into the "OnRowUpdating" event just fine, but there are no NewValues or OldValues. Any suggestions as to how I can get these values?
<asp:GridView ID="gv_Personnel"
runat="server"
OnRowDataBound="gv_Personnel_DataBind"
OnRowCancelingEdit="gv_Personnel_CancelEdit"
OnRowEditing="gv_Personnel_EditRow"
OnRowUpdating="gv_Personnel_UpdateRow"
AutoGenerateColumns="false"
ShowFooter="true"
DataKeyNames="BudgetLineID"
AutoGenerateEditButton="true"
AutoGenerateDeleteButton="true"
>
<Columns>
<asp:BoundField HeaderText="Level of Staff" DataField="LineDescription" />
<%--<asp:BoundField HeaderText="Hrs/Units requested" DataField="NumberOfUnits" />--%>
<asp:TemplateField HeaderText="Hrs/Units requested">
<ItemTemplate>
<%# Eval("NumberOfUnits")%>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="tb_NumUnits" runat="server" Text='<%# Bind("NumberOfUnits")%>' />
</EditItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Hrs/Units of Applicant Cost Share" DataField="" NullDisplayText="0" />
<asp:BoundField HeaderText="Hrs/Units of Partner Cost Share" DataField="" NullDisplayText="0" />
<asp:BoundField FooterStyle-Font-Bold="true" FooterText="TOTAL PERSONNEL SERVICES:" HeaderText="Rate" DataFormatString="{0:C}" DataField="UnitPrice" />
<asp:TemplateField HeaderText="Amount Requested" ItemStyle-HorizontalAlign="Right" FooterStyle-HorizontalAlign="Right" FooterStyle-BorderWidth="2" FooterStyle-Font-Bold="true"/>
<asp:TemplateField HeaderText="Applicant Cost Share" ItemStyle-HorizontalAlign="Right" FooterStyle-HorizontalAlign="Right" FooterStyle-BorderWidth="2" FooterStyle-Font-Bold="true"/>
<asp:TemplateField HeaderText="Partner Cost Share" ItemStyle-HorizontalAlign="Right" FooterStyle-HorizontalAlign="Right" FooterStyle-BorderWidth="2" FooterStyle-Font-Bold="true"/>
<asp:TemplateField HeaderText="Total Projet Cost" ItemStyle-HorizontalAlign="Right" FooterStyle-HorizontalAlign="Right" FooterStyle-BorderWidth="2" FooterStyle-Font-Bold="true"/>
</Columns>
</asp:GridView>
Im not sure if this would help..but this is what i found in msdn site
The Keys, OldValues and NewValues collections are automatically populated only when the GridView control is bound to data by using the DataSourceID property.
Regarding on the GridView control's
RowUpdating event problem, it is the
expected behavior because when we do
not associate GridView(or other
ASP.NET 2.0 databound control) with
DataSource control, it won't
automatically query and fill the
parameters collection of the
updating/deleting/... events. In such
cases, we need to manually extract the
field values from the Template
control.
This is what says a Microsoft employee in here.
In that case you can do it using the ExtractValuesFromCell method to make the NewValues collection yourself.
EDIT:
I found a piece of code in the comments of this blog:
protected void OnRowEditing(object sender, GridViewEditEventArgs e)
{
GridView gv = (GridView)sender;
gv.EditIndex = e.NewEditIndex;
gv.DataBind();
...
}
protected void OnRowUpdating(object sender, GridViewUpdateEventArgs e)
{
GridView gv = (GridView)sender;
for (int i = 0; i < gv.Columns.Count; i++)
{
DataControlFieldCell cell = gv.Rows[e.RowIndex].Cells[i] as DataControlFieldCell;
gv.Columns[i].ExtractValuesFromCell(e.NewValues, cell, DataControlRowState.Edit, true);
}
// now you can use NewValues collection normally
}
Havent tested it, but seems to solve the problem, let me know if it did.
I was doing databinding in my Page_Load event and when I clicked "Update" the PostBack was done, so was the Page_Load event fired. GridView was filled with the old values again, so in myGrid.RowUpdating event I couldn't retrieve new values. If this helps
Bind in the Page PreRender event handler like this:
Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
GridBinder()
End Sub
NB: PreRender takes place after the RowUpdating event.
You need to check the IsPostback in the form load. When the gridview's Update did the postback, it first refreshed with the old values. Use IsPostback to prevent this:
If Not IsPostback Then
' Data bind here
End If
This way, it will not overwrite the "new" gridview values

Dropdownlist results in gridview

I'm having some trouble getting the results of the drop-downs in a gridview, and haven't found any helpful articles for VB code.
What I'm trying to do is build a site for tests. So far I have the gridview built w/the extra column for a drop-down list where the true/false answer will be selected. When the test is completed, there is a submit button. All is well except I need to be able to get the results of each drop-down list on post-back to a variable or array (each test contains 10 questions) so the results can be checked/graded. When the results are determined I would like to display a label in it's place and change the text value accordingly (correct or incorrect), so I'll need to be able to enumerate these as well (i.e. label1.text="Correct!", label2.text="Incorrect!", etc...).
Code so far.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1" BackColor="White" BorderColor="#3366CC"
BorderStyle="None" BorderWidth="1px" CellPadding="1">
<RowStyle BackColor="White" ForeColor="#003399" />
<Columns>
<asp:BoundField DataField="Question" HeaderText="Question"
SortExpression="Question" />
<asp:TemplateField HeaderText="Answer">
<ItemTemplate>
<% If Not IsPostBack Then%>
<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="SqlAnswer"
DataTextField="torf" DataValueField="torf">
</asp:DropDownList>
<%Else%>
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
<%End If%>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<FooterStyle BackColor="#99CCCC" ForeColor="#003399" />
<PagerStyle BackColor="#99CCCC" ForeColor="#003399" HorizontalAlign="Left" />
<SelectedRowStyle BackColor="#009999" Font-Bold="True" ForeColor="#CCFF99" />
<HeaderStyle BackColor="#003399" Font-Bold="True" ForeColor="#CCCCFF" />
</asp:GridView>
The preceding code loads 10 rows, 2 columns (column1:Question | column2-[DropDownLists]:Answer). I'm a freshman when it comes to development, so if you need additional info let me know.
Here is how I handled it:
created a page level private variable to hold our list of correct/incorrect values
Private Answers as New List(Of Boolean) 'creates a strongly typed list of t/f values
in Page.Load
if IsPostBack then
'iterate through each row
for each gridRow As GridViewRow in GridView1.Rows
'get the selected value for this answer
Dim answer as string = CType(gridRow.FindControl("DropDownList1"),DropDownList).SelectedValue
'add this answer to the list
Answers.Add(IsCorrectAnswer(answer))
next
end if
the IsCorrectAnswer function determines whether or not the answer given for this question is correct and returns a Boolean value. You would need to write this function to suit your needs.
in Button1.Click handler
'rowCounter will act as an index to the answers
Dim rowCounter as Integer = 0
For Each gridRow as GridViewRow in GridView1.Rows
'grid_RowDataBound handles the binding of single row
grid_RowDataBound(gridRow, rowCounter)
rowCounter+=1
Next
finally
Private Sub grid_RowDataBound(gridRow as GridViewRow, rowCounter as Integer)
'make the dropdown invisible
CType(gridRow.FindControl("DropDownList1"),DropDownList).Visible = False
'because we'll be acting on two properties of the label, I shove it in a variable first for ease of access
Dim label As Label = CType(gridRow.FindControl("Label1"),Label)
'set the label to visible
label.Visible = True
'set the text
label.Text = Iif(Answers(rowCounter),"Correct", "Incorrect")
End Sub
Someone probably has a cleaner solution than this, but I do know this works, at least as far as I understand the issue you are facing.
Good luck
What about binding the Visible attribute to Page.IsPostBack (note this is in C# since I'm not familiar with the syntax for VB.NET... I'm sure something similar would work):
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="SqlAnswer"
DataTextField="torf" DataValueField="torf" Visible='<%# !Page.IsPostBack %/>></asp:DropDownList>
<asp:Label ID="Label1" runat="server" Text="" Visible='<%# Page.IsPostBack %/></asp:Label>
</ItemTemplate>
check the RowDataBound event of the gridview object. It takes two parameters:
(byval sender as Object, byval e as GridViewRowEventArgs). With it, you can set the value of the label in each row to 'Correct' or 'Incorrect' on the postback.
see the example at
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.rowdatabound.aspx
for more information
as for getting the answers into a variable, here are a couple of options
1) check viewstate. It has some overhead, so be cautious with it.
2) save the data to a Session object

Resources