Checkbox on GridView always returning False - asp.net

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.

Related

GridView Row FindControl(x) Text is blank

I have a GridView where I want to hide some of the rows when the price is 0. When I try to check the value I get a blank string for all rows.
Markup: non relevant rows have been removed for readability. getProductInfo and getPrice are lookup functions receiving and returning strings
<asp:GridView ID="gvRebuild" runat="server" AutoGenerateColumns="false" Width="100%" OnRowDataBound="gvRebuild_RowDataBound">
<Columns>
<asp:BoundField ... />
<asp:TemplateField ... />
</asp:TemplateField>
<asp:TemplateField HeaderText="Price" ItemStyle-Width="12%">
<ItemTemplate>
<asp:Label runat="server" ID="price" ><%# getPrice(getProductInfo(Eval("fieldName")))%></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ... />
</Columns>
</asp:GridView>
Code Behind:
Protected Sub gvRebuild_RowDataBound(sender As Object, e As GridViewRowEventArgs)
Dim p As Label = e.Row.FindControl("price")
If p IsNot Nothing Then
Debug.Print(String.Format("*{0}*", p.Text))
If p.Text = "$0.00" Then
e.Row.Visible = False
End If
End If
End Sub
The debug statement is confirming that all values found in the "price" control are blank. I have also confirmed via debugger that the getPrice function is returning the correct value and firing before the RowDataBound event handler for each row.
You have to check the RowType. The first row will be the header row. The header row does not contain the TextBox, hence the NULL error.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//use findcontrol here
}
}
VB
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If (e.Row.RowType = DataControlRowType.DataRow) Then
'use findcontrol here
End If
End Sub
Update
I see what you mean now. It is the value that is NULL not the control itself.
I did some testing and it turns out that if you use your method it does not work. But change it to this and it will.
<asp:Label runat="server" ID="price" Text='<%# getPrice(getProductInfo(Eval("fieldName"))) %>'></asp:Label>
It seems that the binding of data inside the tag is done after the row or gridview has completed, but the Text property is set right away.

pass ID value to OnCheckedChange event in code behind

I have a gridview that has one checkbox for each row of data.
When the checkbox is checked or unchecked, I need to update a bit flag in my database.
I'm trying to use the OnCheckedChanged event.
It does fire, however I am getting a null error which has to do with an ID.
My problem is, I'm not quite sure how to get the needed ID to the OnCheckedChanged event code.
I need this ID to update the appropriate row in my database.
I found a few relavent questions on StackOverflow but none of the supplied answers really helped me out.
Thanks!
My gridview code:
<asp:GridView ID="gvlisting" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField HeaderText="Item Is Ready">
<ItemTemplate>
<asp:CheckBox ID="isReady" runat="server" AutoPostBack="true" OnCheckedChanged="isReady_CheckedChanged" Checked='<%#isReady(CInt(Eval("isReady")))%>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Item Name">
<ItemTemplate>
<asp:Label ID="itemName" runat="server" Text='<%#cleanString(Eval("itemName").ToString())%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
code behind:
Public Sub isReady_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim box As CheckBox = DirectCast(sender, CheckBox)
If box.Checked = True Then
'custom code for executing an SQL UPDATE statement
db.ExecuteNonQuery(AddIsreadyFlag, New SqlParameter("#itemID", Me.ID))
Else
db.ExecuteNonQuery(RemoveIsreadyFlag, New SqlParameter("#itemID", Me.ID))
End If
End Sub
Me.ID is the ID of the Page since Me is the current page-instance.
You could add another template-field with the ID:
<asp:TemplateField HeaderText="Item-ID" Visible="false">
<ItemTemplate>
<asp:Label ID="itemID" runat="server" Text='<%# Eval("itemID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Now you can use the NamingContainer to get the row and FindControl to get the label:
Public Sub isReady_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim box As CheckBox = DirectCast(sender, CheckBox)
Dim row = DirectCast(box.NamingContainer, GridViewRow)
Dim itemID = DirectCast(row.FindControl("itemID"), Label).Text
If box.Checked = True Then
'custom code for executing an SQL UPDATE statement
db.ExecuteNonQuery(AddIsreadyFlag, New SqlParameter("#itemID", itemID))
Else
db.ExecuteNonQuery(RemoveIsreadyFlag, New SqlParameter("#itemID", itemID))
End If
End Sub
You can also try to add a custom attribute in the OnDataBinding event and retrieve the value in de CheckChanged event.
protected void chkEnabled_DataBinding(object sender, EventArgs e)
{
CheckBox chk = (CheckBox)sender;
string id = Eval("Id").ToString();
chk.Attributes.Add("data-id", id);
}
protected void chkEnabled_CheckedChanged(object sender, EventArgs e)
{
CheckBox chk = (CheckBox)sender;
string id = chk.Attributes["data-id"];
}
Add the ID column to the grid, then if needed set it's visible property to false.
You can get the Gridview's selected row then get cell the value for ID column (the column does not need to be visisble, but it needs to exist in the grid).
var someVar = gvlisting.SelectedRow.Cells[0].Text; //change 0 to correct column
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.selectedrow(v=vs.110).aspx
You may need to do this in a SelectedIndexChanged but i doubt that, if that is the case you can easily get the data from the cell using the above or findcontrol like...How to find control in TemplateField of GridView?

ASP.NET GridView Data which i set on RowDatabound event loses after post back

I have an asp.net page where i have a gridview control which bind data from a DataTable.
In my 5 th column of the grid i am showing a Radio button list which has 2 Radio button items (Yes or No). For Some rows i will not show the RadioButton control, if the 4 th column cell value is empty. It works fine.But in my button click event (postback), the Grid is showing the Radio button list for those cells which was not shown initially. I have enabled ViewState for page and Control
This is my code
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns=false
DataKeyNames="RequestDetailId" ondatabound="GridView1_DataBound" EnableViewState ="true" AllowPaging=false
onrowdatabound="GridView1_RowDataBound">
<Columns>
<asp:BoundField DataField="RequestDetailId" HeaderText="Request Detail Id" />
<asp:BoundField DataField="Item" HeaderText="Item" />
<asp:BoundField DataField="Status" HeaderText="Status" />
<asp:BoundField DataField="NewOffer" HeaderText="New Offer" />
<asp:TemplateField HeaderText="Your Response" ItemStyle-CssClass="radioTD">
<ItemTemplate>
<asp:RadioButtonList ID="radioList" runat="server">
<asp:ListItem Text="Yes" Value="Accept"></asp:ListItem>
<asp:ListItem Text="No" Value="Reject"></asp:ListItem>
</asp:RadioButtonList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
in code behind
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadItemDetails();
}
}
private void LoadItemDetails()
{
DataTable objDt= GetGridDataSource();
if (objDt.Rows.Count > 0)
{
GridView1.DataSource = objDt;
GridView1.DataBind();
}
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(String.IsNullOrEmpty (e.Row.Cells[3].Text.Trim())||(e.Row.Cells [3].Text ==" "))
{
e.Row.Cells[4].Text = "";
}
}
My results are
Before Postback
After Postback
How do i maintain the content after postback ? Thanks
The problem is that you are setting the Text of the GridView table cell to an empty string rather than setting the visibility of the RadioButtonList control to false.
Clearing the Text property is removing the markup for the RadioButtonList on the first load, but on postback the RowDataBound event is not fired and the RadioButtonList control is recreated and displayed again.
To avoid this you could find the control and set its visibility to false, this will then be remembered across postbacks.
Try the following:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (String.IsNullOrEmpty(e.Row.Cells[3].Text.Trim()) || (e.Row.Cells[3].Text == " "))
{
RadioButtonList radioList = (RadioButtonList)e.Row.FindControl("radioList");
radioList.Visible = false;
}
}
Hope this helps.
you can do something like this ..
from the description of the problem. it sounds as if you are doing the databinding in the code behind. in such case asp.net does not preserve the datasource in the viewstate for you. try retrieving the data and storing it in the ViewState hashtable object with something like
ViewState["GridviewData"] = GridviewData
and retreiving it from there between postbacks

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

give the ID as a custom attribute to checkbox in a grid for manual update

I like to update just the value of my checkbox in a asp grid.
so i thought i bind the id to the checkbox ( but how?) and fire an update in code behind by clicking the checkbox.
but how can I get the ID, and where I have to bind this id to get it in code behind in the event?
Thanks
Here is what I've managed to do. (Be aware there should be an easier way to do this. I'm very new to ASP.NET)
Here you have a TemplateField in a GridView. Inside it there is an UpdatePanel and the CheckBox is inside it. This is done to make the checking of the TextBox do post in the backgroung (ajax). You might not need it (UpdatePanel) at all.
<asp:TemplateField HeaderText="Private" SortExpression="IsPrivate">
<ItemTemplate>
<asp:UpdatePanel ID="upIsPrivate" runat="server" UpdateMode="Always" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:CheckBox ID="chkIsPrivate" runat="server" OnCheckedChanged="chkIsPrivate_CheckedChanged" AutoPostBack="true" />
</ContentTemplate>
</asp:UpdatePanel>
</ItemTemplate>
</asp:TemplateField>
And this is the method that handles this. Notice that I get the Id from the GridViewRow that contains the CheckBox:
GridViewRow row = (GridViewRow)((CheckBox)sender).Parent.Parent.Parent.Parent;
protected void chkIsPrivate_CheckedChanged(object sender, EventArgs e)
{
if (editMode)
{
GridViewRow row = (GridViewRow)((CheckBox)sender).Parent.Parent.Parent.Parent;
Int32 id = (Int32)uxPhoneCallList.DataKeys[row.RowIndex]["Id"];
CheckBox isPrivate = (CheckBox)row.FindControl("chkIsPrivate");
PhoneCall phoneCall = PhoneCallManager.GetById(id);
...
}
}

Resources