pass ID value to OnCheckedChange event in code behind - asp.net

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?

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.

Iterating through EditItemTemplate textboxes in asp:Gridview

I have a gridview displaying data within a template field which requires more information about the record to be displayed by clicking on a linkbutton. Right now, I have the "details" linkbutton display the information by calling the edit command on the gridview so that it switches to the EditItemTemplate. Within the EditItemTemplate I have a linkbutton for cancel and then an edit button that, when clicked, displays the update button with the update command, but I need it to iterate through that row and set all the textboxes within the EditItemTemplate to ReadOnly=false so as to allow them to be edited before the update command is selected. Here is a summary of the code:
<ItemTemplate>
*basic information displayed*
<asp:LinkButton runat="server" CommandName="Edit" Text="Details"></asp:LinkButton>
</ItemTemplate>
<EditItemTemplate>
*A bunch of readonly textboxes that display the extra information*
<asp:LinkButton runat="server" CommandName="Update" Text="Update" Visible="false"></asp:LinkButton>
<asp:LinkButton runat="server" Text="Edit" OnClick="editButton_Click"></asp:LinkButton>
</EditItemTemplate>
And the code for the event which makes the buttons appear the way I want, but I'm not sure how to iterate through the EditItemTemplate, or even if this is what I should do:
Protected Sub editButton_Click(sender As Object, e As EventArgs)
sender.FindControl("updateButton").Visible = True
sender.FindControl("editbutton").Visible = False
For Each t In ?EditItemTemplate?
Dim textbox = TryCast(t, System.Web.UI.WebControls.TextBox)
If textbox IsNot Nothing Then
textbox.ReadOnly = False
End If
Next
End Sub
So my question is either how to get this to work, or how I should set up the GridViewCommands otherwise
You should use a PlaceHolder in your EditItemTemplate. Place all of your Controls/LinkButtons inside this placeholder.
<EditItemTemplate>
<asp:PlaceHolder ID="TestPlaceHolder" runat="server">
// Sample Link Buttons
<asp:LinkButton runat="server" CommandName="Update" Text="Update"
Visible="false"></asp:LinkButton>
<asp:LinkButton runat="server" Text="Edit" OnClick="editButton_Click"></asp:LinkButton>
// Sample Text Box
<asp:TextBox runat="server" ID="FirstName" ...>...</TextBox>
</asp:PlaceHolder>
</EditItemTemplate>
Handle the RowEditing event of GridView. Inside the edit event handler, first find the Placeholder, then use the PlaceHolder's Controls property to iterate over the Controls...
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
// Get the Placeholder for the row being edited.
PlaceHolder testPlacehldr =
GridView.Rows[e.NewEditIndex].FindControl("TestPlaceholder") as PlaceHolder;
// Iterate over the controls
if(testPlacehldr.Controls.Count > 0)
{
foreach (Control ctrl in testPlacehldr.Controls)
{
if (ctrl is LinkButton)
{
LinkButton lnkBtn = ctrl as LinkButton
if(lnkBtn.Text== "Update")
{
lnkBtn.Visible = false;
}
// More IF conditions follow....
}
if (ctrl is TextBox)
{
TextBox txtBox = ctrl as TextBox;
if(txtBox.ID == "FirstName")// use any property of TexBox you prefer
{
txtBox.ReadOnly= true;
}
// More IF conditions follow....
}
}
}
//At the End, set the EditIndex and Bind the data
GridView1.EditIndex = e.NewEditIndex;
BindGridViewData();
}
I hope you can workout the logic yourself now for hiding/showing the controls.
So I figured out how to do it (needed it in vb) by using the placeholder within the EditItemTemplate, here's the code behind it:
Protected Sub editButton_Click(sender As Object, e As EventArgs)
sender.FindControl("editbutton").Visible = False
sender.FindControl("updateButton").Visible = True
Dim testPlacehldr As PlaceHolder = sender.FindControl("TestPlaceholder")
If testPlacehldr.Controls.Count > 0 Then
Dim btn As LinkButton = sender.FindControl("editButton")
If btn.Visible = False Then
For Each ctrl As Control In testPlacehldr.Controls
If ctrl.GetType Is GetType(TextBox) Then
Dim box As TextBox = TryCast(ctrl, TextBox)
box.ReadOnly = False
End If
Next
End If
End If
End Sub
This works fine for what I need it to do. Credit to the user R.C. for the idea about placeholders

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.

Can't find dropdown list in RowDataBound event

I'm following this example http://www.codeproject.com/KB/webforms/Editable_GridView.aspx to build an editable GridView control.
I have this code in my GridView:
<asp:TemplateField HeaderText="Negócio">
<ItemTemplate>
<asp:Label ID="lblNegocio" runat="server" Text='<%# Eval("Negocio") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddlNegocio" runat="server" />
</EditItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="ddlNewNegocio" runat="server" />
</FooterTemplate>
Now, I'm trying to fill the dropdown in the EditItemTemplate with some dynamic values just as the example says, in the RowDataBound Event of the grid. But when I do this, the FindControl method always returns Nothing:
Protected Sub gdvRegraRotationDefault_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gdvRegraRotationDefault.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
Dim ddlNegocio As DropDownList = e.Row.FindControl("ddlNegocio")
End If
End Sub
If I can't find the Dropdown I can't load the values in it and when I'm going to edit de entry it will be empty.
Can someone help me?
Thank you (:
Please use the RowEditing-Event, as your DropDownList should only be shown when clicking Edit.
But first, you have to bind the GridView newly as the GridView now needs to render different controls for the edit row:
protected void gdvRegraRotationDefault_RowEditing(object sender, GridViewEditEventArgs e)
{
gdvRegraRotationDefault.EditIndex = e.NewEditIndex;
gdvRegraRotationDefault.DataBind();
GridViewRow row = gdvRegraRotationDefault.Rows[e.NewEditIndex];
DropDownList ddl = row.FindControl("ddlNegocio") as DropDownList;
//now do databinding for DropDownList
}
The FindControl always return null because when your in the RowDataBound event you can get the label only.
If you want to fill the DropDownList when you click the edit button on the grid, then you have to use the GridViewRowEditing event.
In the RowDataBound event, simply add the following conditional:
if (myGridView.EditIndex == e.Row.RowIndex)
{
//do work
}

Gridview template radiobuttonlist SelectedInxedChanged, Getting the row the list was in when it fired

I have a Gridview in which one of the template fields has a radiobuttonlist and a dropdownlist. How can I access the row that the radiobuttonlist is in on the SelectedIndexChanged event, so I don't end up updating all of the dropdownlist inside the that template field of the gridview. I don't have any code currently but any help would be greatly appreciated
<asp:TemplateField HeaderText="Column with ListControls" >
<ItemTemplate>
<asp:DropDownList ID="DropdownList1" OnSelectedIndexChanged="SomethingChanged" AutoPostBack="true" runat="server" >
<asp:ListItem Text="1"></asp:ListItem>
<asp:ListItem Text="2"></asp:ListItem>
</asp:DropDownList>
<asp:RadioButtonList ID="RadioButtonList1" OnSelectedIndexChanged="SomethingChanged" AutoPostBack="true" runat="server">
<asp:ListItem Text="1"></asp:ListItem>
<asp:ListItem Text="2"></asp:ListItem>
</asp:RadioButtonList>
</ItemTemplate>
</asp:TemplateField>
Codebehind VB.NET:
Protected Sub SomethingChanged(ByVal sender As Object, ByVal e As EventArgs)
'in this example this handler is used for both, Dropdownlist and RadiobuttonList'
Dim listControl = DirectCast(sender, ListControl)
Dim row = DirectCast(listControl.NamingContainer, GridViewRow)
Dim item = listControl.SelectedItem
'with FindControl on the row you could also find controls in other columns...'
End Sub
C#:
protected void SomethingChanged(object sender, EventArgs e)
{
//in this example this handler is used for both, Dropdownlist and RadiobuttonList
var listControl = (ListControl)sender;
var row = (GridViewRow)listControl.NamingContainer;
var item = listControl.SelectedItem;
//with FindControl on the row you could also find controls in other columns...
}

Resources