GridView's NewValues and OldValues empty in the OnRowUpdating event - asp.net

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

Related

OnCheckChanged not Firing when Unchecked

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

Handle button click in gridview in combination with rowclick

I have a gridview in my asp.net application. We've added code to intercept row clicks anywhere on a row.
This works perfectly. Whenever a row is clicked, the RowCommandevent is fired.
(in this case it redirects the user to a different page)
Now I want to add a column with an Image which, when clicked, should not redirect the user, but fire some Javascript.
However, while the javascript is fired, the RowClick is also fired.
Is there a way to temporarily disable the RowClick?
Edit: Updated code
The gridview:
<asp:GridView id="OpleidingView" runat="server" SkinID="sknGridView" ShowHeader="false" AutoGenerateColumns="False" DataKeyNames="OPLEIDING_ID, OPLEIDING_OMSCHRIJVING, EIGENAAR">
<Columns>
<asp:Boundfield DataField="OPLEIDING_OMSCHRIJVING"></asp:BoundField>
<asp:Boundfield DataField="OPLEIDING_COLO_CODE"></asp:BoundField>
<asp:Boundfield DataField="OPLEIDING_COHORT"></asp:BoundField>
<asp:Boundfield DataField="OPLEIDING_CODE"></asp:BoundField>
<asp:Boundfield DataField="OPLEIDING_VERSIE"></asp:BoundField>
<asp:Boundfield DataField="OPLEIDING_LEERWEG"></asp:BoundField>
<asp:Boundfield DataField="OPLEIDING_NIVEAU"></asp:BoundField>
<asp:Boundfield DataField="OPLEIDING_VERWIJDERD"></asp:BoundField>
<asp:templatefield>
<ItemTemplate>
<asp:Image ID="imgDelen" runat="server"/>
</ItemTemplate>
</asp:templatefield>
</Columns>
</asp:GridView>
The Javascript function:
function Test()
{
alert("hi");
return false;
}
The RowDataBound event:
Protected Sub OpleidingView_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles OpleidingView.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Attributes("onclick") = ClientScript.GetPostBackEventReference(Me.OpleidingView, "Select$" & e.Row.RowIndex)
e.Row.ID = "Disable" & e.Row.RowIndex.ToString
Dim img As Image = CType(e.Row.FindControl("imgdelen"), Image)
img.ImageUrl = "~/Images/DefaultTheme/delen_zwart.png"
img.Attributes.Add("onclick", "return Test();")
End If
End Sub

Checkbox on GridView always returning False

I have a GridView with a Checkbox on the first column:
<asp:GridView ID="dgNumeradores" runat="server" AutoGenerateColumns="False" CellPadding="4" DataKeyNames="ItemID">
<Columns>
<asp:TemplateField HeaderText="Seleccionar">
<ItemTemplate>
<asp:CheckBox runat="server" ID="chkChecked" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Item" DataField="Description">
</asp:BoundField>
<asp:BoundField HeaderText="Plantilla" DataField="Template">
</asp:BoundField>
</Columns>
</asp:GridView>
Now in the code behind I try to update the Checked column on the DataTable acting as datasource for the GridView (since, as you can see above, the Checkbox column is not bound to the datasource for reasons you probably know.):
Protected Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Try
For Each dr As GridViewRow In Me.dgNumeradores.Rows
Me.itemsNumTable.Select("ItemID = '" & dgNumeradores.DataKeys(dr.RowIndex).Value & "'")(0)("Checked") = DirectCast(dr.Cells(0).FindControl("chkChecked"), CheckBox).Checked
Next
'Some more unimportant-for-this-question code
Catch ex As Exception
tableInfo.ShowError(ex.Message)
End Try
End Sub
The thing is that the Checkbox.Checked always returns False.
How can I get the checked state of the Checkboxes in this scenario? Or what would be the best approach into updating the aforementioned column?
P.S. Note that click on the checkboxes doesn't post back. Nothing happens on the page until the user clicks Save (and that is the intended behavior).
Are you binding the GridView in Page Load? If that is the case use IsPostBack
IF Not IsPostBack Then
DataBind()
End IF
Should you not have the AutoPostback property set to true?
<asp:CheckBox runat="server" ID="chkChecked" AutoPostback="true" />
I have two columns in my GridView. The first column contains filenames,
the second column contains Checkboxes. Once the user has selected an arbitrary
number of Checkboxes then by clicking a button the selected files can be
downloaded.
My markup is as follows
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField HeaderText="Available Schemas"
DataField="SchemaFileName"
SortExpression="UserId">
</asp:BoundField>
<asp:TemplateField HeaderText="Select Schema">
<ItemTemplate>
<asp:CheckBox runat="server" ID="SelectedFiles" checked= '<%# Eval("checkValue") %>'/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
My CodeBehind part is as follows
protected void Page_Load(object sender, EventArgs e)
{
GenerateDownloadLinks();
if (!IsPostBack)
{
GridView1.DataSource = listOfData;
GridView1.DataBind();
}
}
listOfData is populated in GenerateDownloadLinks() and then it is bind to GridView1.
Once the user selected files and clicks download then my code loops through
the rows of the GridView and when the CheckBox is checked it updates the initially
false value of the data entry to make sure which files should be made available for
download.
protected void GetFiles_Click(object sender, EventArgs e)
{
int i = 0;
foreach (GridViewRow row in GridView1.Rows)
{
CheckBox chkRow = (row.Cells[1].FindControl("SelectedFiles") as CheckBox);
if (chkRow.Checked)
{
listOfData[i].CheckValue = true;
}
i++;
}
}
Gridview fills perfectly even when it is not binded in Page.IsPostBack block, but here checkbox will always return false.
Bind gridview in Page.IsPostBack, and it would run perfectly fine.
Use below code
IF Not IsPostBack Then
DataBind()
End IF
And then Checkbox.Checked will return true.

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

DataBound DropDownList in DataGrid - order of binding

I have a DataGrid that looks like this (slightly simplified here):
<asp:DataGrid ID="grdQuotas" runat="server" AutoGenerateColumns="False">
<HeaderStyle CssClass="quotas-header" />
<Columns>
<asp:TemplateColumn>
<HeaderTemplate>
Max order level</HeaderTemplate>
<ItemTemplate>
<asp:DropDownList ID="ddlMaxOrderLevel" runat="server" DataSourceID="xdsOrderLevel"
DataTextField="Text" DataValueField="Value" SelectedValue='<%# Bind("MaxOrderLevel") %>'>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
<asp:XmlDataSource ID="xdsOrderLevel" runat="server" DataFile="~/App_Data/OrderLevels.xml">
</asp:XmlDataSource>
In my Page_Load event handler I am creating a DataTable containing default values and DataBinding it to the DataGrid.
The problem is that this is taking place before the DropDownList ddlMaxOrderLevel has been bound to its DataSource, so I get a runtime error telling me that the SelectedValue cannot be set.
If ddlMaxOrderLevel was not in a DataGrid I could just call DataBind() on it. However I cannot do that in this scenario - since it is in an ItemTemplate.
Can anyone suggest a workaround or alternate approach?
You could do the Databinding of the DropDownlist in the Databound event of the DataGrid.
Edit:
I will give you an example that i have tested:
protected void dg_ItemDataBound(object sender, DataGridItemEventArgs e)
{
if (e.Item.ItemType != ListItemType.Header && e.Item.ItemType != ListItemType.Footer)
{
DropDownList dl = (DropDownList)((DataGridItem)e.Item).FindControl("ddlMaxOrderLevel");
dl.DataSource = levels;
dl.DataBind();
dl.SelectedValue = ((DataRowView)e.Item.DataItem)["number"].ToString();
}
}
Create another DataSource and bind it to the DataGrid. Where the SelectMethod would return the default values in a simple object.
Then all the binding should happily work together.

Resources