find control not working gridview - asp.net

I have a page which contains gridview and button now i want to add gridview values to database table when i click on button, but when i click on button and try to get value using find control its not showing any value it shows value as blank.
my code is given below
aspx page
<%# Page Title="" Language="C#" MasterPageFile="Masters.Master" AutoEventWireup="true" EnableEventValidation ="false" CodeBehind="test.aspx.cs" Inherits="test" UICulture="hi-IN" Culture="hi-IN" %>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnDataBound="GridView1_DataBound"
OnRowDataBound="GridView1_RowDataBound" BackColor="White" BorderColor="White"
BorderStyle="Solid" BorderWidth="1px" CellPadding="3" ForeColor="Black" GridLines="Vertical">
<asp:TemplateField Visible="true">
<HeaderTemplate>
<asp:Label ID="lbl4" runat="server" Text="test."></asp:Label>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="lbltestno" runat="server" Text='<%# Bind("testing") %>' Visible="true"></asp:Label><br style="mso-data-placement:same-cell;"/>
</ItemTemplate>
</asp:TemplateField>
.cs page
on button click
foreach (GridViewRow GvRow in GridView1.Rows)
{
Label lblvinnos = (Label)GvRow.FindControl("lbltestno");
}
Please note that this page is working fine when i use without master page but when i am using master page its showing find control values as null
I just checked its finding textbox value not of labels any particular reason?

Try in Button cliked event like:
int indexcount = 0;
foreach (GridViewRow row in GridView1.Rows)
{
// get value from label on each row in gridview
string value = (GridView1.Rows[indexcount].FindControl("lbltestno") as Label).Text;
indexcount++;
}

You have to find it in cell, cell_index is actual index (starts with 0) of cell where control resides.
Label lblvinnos = (Label)GvRow.Cells[cell_index].FindControl("lbltestno");

create button inside a template field
trigger it inside your gridview_rowcommand method
applies per row only
GridViewRow row = (GridViewRow)(((ImageButton)e.CommandSource).NamingContainer);
string your_variable = Convert.ToDecimal(((TextBox)row.FindControl("your control here")).Text);
hope it helps

Related

GridView location of button how to determine the Cells[?] e.Row.Cells[0].Controls[0];

I placed a few Buttons above my GridView
I had read an article about doing this Update/Cancel buttons without having explicit invasive Edit link button which turns into a Update / Cancel links
It seems that the article http://www.binaryintellect.net/articles/4afd676c-693b-40e2-ac86-129429c71078.aspx
mentions that
" So, e.Cells[0] gives you the first table cell. If you have placed this column at some other position (end of all the other columns, for example) then you should change the index accordingly. Controls[0] gives you reference of the Update button. "
I do not know that Controls[0] is the update button ?
How would I how the Cells[?] of the update button as well ?
Error:
Unable to cast object of type 'System.Web.UI.LiteralControl' to type 'System.Web.UI.WebControls.LinkButton'.
LinkButton updateBtn = (LinkButton)e.Row.Cells[0].Controls[0];
Line 339: string updateScript = ClientScript.GetPostBackClientHyperlink(updateBtn, "");
Line 340: Button1.Attributes["onclick"] = updateScript;
HTML
<asp:Button ID="Button1" runat="server" Text="Update" />
<asp:Button ID="Button2" runat="server" Text="Cancel" />
<asp:GridView ID="GridView1" CssClass="table" runat="server" AutoGenerateColumns="False" DataKeyNames="id" OnRowCommand="GridView1_RowCommand" Caption='<table border="1" width="100%" cellpadding="0" cellspacing="0" bgcolor="CornflowerBlue"><tr><td><B>NORTH</B></td></tr></table>'
CaptionAlign="Top" OnRowEditing="GridView1_RowEditing" OnRowUpdating="GridView1_RowUpdating" OnRowCancelingEdit="GridView1_RowCancelingEdit" OnRowDataBound="GridView1_RowDataBound" Width="100%" OnSelectedIndexChanged="OnSelectedIndexChanged">
Code:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
if (e.Row.RowIndex == GridView1.EditIndex) {
LinkButton updateBtn = (LinkButton)e.Row.Cells[0].Controls[0];
string updateScript = ClientScript.GetPostBackClientHyperlink(updateBtn, "");
Button1.Attributes["onclick"] = updateScript;
string cancelScript = string.Format("javascript:__doPostBack('{0}','Cancel${1}')", GridView1.ID, e.Row.RowIndex);
Button2.Attributes["onclick"] = cancelScript;
EDIT/UPDATE:
If I delete a visible=false from a Edit button this is the HTML in the gridview
<asp:CommandField ButtonType="Link" ShowEditButton="true" EditText="edit" ItemStyle-Width="5px">
<ItemStyle Width="5px"></ItemStyle>
</asp:CommandField>
Chrome Browser view a row in edit mode
Update
Cancel
This code works as expected...
However The Update / Cancel button above the grid are not getting the correct information
<a onclick="javascript:__doPostBack('Button11','');" id="Button11" href="javascript:__doPostBack('Button11','')">Update</a>
<a onclick="javascript:__doPostBack('GridView1','Cancel$10');" id="Button22" href="javascript:__doPostBack('Button22','')">Cancel</a>
You should be able to access the buttons with their given ID in the code behind since they are not part of the gridview. Try replacing
LinkButton updateBtn = (LinkButton)e.Row.Cells[0].Controls[0];
with
Button updateBtn = Button1;

How to read the data of the row when clicked the button in the same row

I have the data displayed in the grid as follows:
StartDate Enddate Button
16/3/2013 17/3/2013 Signup---> this is an ASP button
18/3/2013 19/3/2012 Signup----> this is an ASP button
20/3/2012 20/3/2012 Signup----> this is an ASP button
I want asp.net with c# code when i clicked on first row signup button i want to get the data of the first row. If clicked on second row i want only the data of the second row startdate and end time. How can i acheive this? Please hep me in this regard.
In the asp button, Set properties: CommandName="SignUp" CommandArgument='<%# Container.DataItemIndex%>'
Now, when this button is clicked it calls Gridview's RowCommand Event
In that event e.CommandArgument contains your Row Number.
GridViewRow gvr= gvLinkImages.Rows[e.CommandArgument];
Now you can use gvr.Cells[column number] to get the particular text (Not recommended)
or use findcontrol to get the label or literal of the start/end date( assuming you are using Templatefields)
Sample code below
C#
protected void gvResults_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "SignUp")
{
int rwNumber = Convert.ToInt32(e.CommandArgument);
GridViewRow gvr = gvResults.Rows(rwNumber);
System.DateTime rowStartDate = default(System.DateTime);
System.DateTime rowEndDate = default(System.DateTime);
//If you are using Templatefields
Literal lblRowStartDate = gvr.FindControl("lblStartDate") as Literal;
Literal lblRowEndDate = gvr.FindControl("lblEndDate") as Literal;
rowStartDate = Convert.ToDateTime(lblRowStartDate.Text);
rowEndDate = Convert.ToDateTime(lblRowEndDate.Text);
//Incase you are not using TemplateFields or Autobinding your grid
rowStartDate = Convert.ToDateTime(gvr.Cells[0].Text);
rowEndDate = Convert.ToDateTime(gvr.Cells[1].Text);
}
}
ASPX
<asp:GridView runat="server" ID="gvResults" AutoGenerateColumns="false" OnRowCommand="gvResults_RowCommand">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Literal runat="server" ID="lblStartDate" Text='<%#Container.DataItem.StartDate%>'></asp:Literal>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Literal runat="server" ID="lblStartDate" Text='<%#Container.DataItem.EndDate%>'></asp:Literal>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button runat="server" ID="btnSignUp" CommandName="SignUp" CommandArgument="<%# Container.DataItemIndex %>" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

ASP.NET Gridview: How do I stop a <span></span> within a Gridview from resetting when posting back?

I have a Gridview which contains some controls which are updated from the server when the user makes a selection from a gridview.
After making their selection from a drop down list the user can enter a percentage into a textbox on a row and I have some javascript which then carries out some calculations and outputs to a span within an item template in the Gridview.
This all works but if the user then makes another drop down list selection on any row all the spans in the gridview are reset to blank (I've tried with various controls, both asp.net and html).
This is all inside an Update Panel.
Code:
<asp:GridView runat="server" ID="gdvIngredients" AutoGenerateColumns="false" CssClass="table table-stripped"
GridLines="None" Visible="false" ShowFooter="true" EnableViewState="true">
<Columns>
<asp:TemplateField Visible="false">
<ItemTemplate>
<asp:Label runat="server" ID="lblId" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Ingredient" ItemStyle-Width="12%">
<ItemTemplate>
<asp:DropDownList runat="server" ID="ddlName" AutoPostBack="true" OnSelectedIndexChanged="ddlName_SelectedIndexChanged"
ForeColor="Black" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="%" ItemStyle-Width="6%">
<ItemTemplate>
<asp:TextBox runat="server" Text="0" Width="50px" ID="txtPercentage" onkeyup="calculate(this);"
ForeColor="Black" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="kj" ItemStyle-Width="6%">
<ItemTemplate>
<asp:Label runat="server" ID="lblKj" CssClass="Kj" Style="display: none;" />
<span runat="server" id="spnKj" class="NewKj">0</span>
</ItemTemplate>
From your question what i have understood is that you are doing calculation in javascript and assigning it to span,but when next postback happens the value is not retained...If i am right i would suggest you to try the following steps.Use HiddenFields also to assign Values as HiddenFields Retain values during PostBacks.
Add Hidden field in Item Template
Set "calculate" function to Textbox from Codebehind(from rowdatabound event) & also pass the currosponding HiddenField Value to it as calculate(this,'HiddenFieldId');
protected void grd_RowDataBound(object sender,GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
HiddenField hdn = ((HiddenField)e.Row.FindControl("HiddenFieldID"));
TextBox txtPercentage = (TextBox)e.Row.FindControl("txtPercentage");
HtmlGenericControl spnKj=(HtmlGenericControl )e.Row.FindControl("spnKj");
txtPercentage.Attributes["onClick"]="calculate(this,'"+hdn .ClientID+"');"
spnKj.innerHTML=hdn.Value;
}
}
Javascript:
Assign Calculated Value to Hidden Field...
function calculate(hdnID)
{
var CalcValue=//do your Calculation
document.getElementByID(hdnID).Value=CalcValue;
}
3.In the DropDown PostBack Event Bind the GridView Again.
The above code should take care of the Issue You are facing.
You can use the "AutoPostBack" property to control the Postback event of some controls.
Have a look if your dropdown list selection do any PostBack.
If it does, then span values disappear, becuase Span is not ASP.NET webcontrol. After pages is postback, asp.net webcontrol values are restored from ViewState. So, spans doesn't have ViewState and no values are restored.
You can try to change your tag to
<span runat="server" id="spanIDHere">SomeValue here</span>
runat="server" makes span to be HtmlGenericControl and maintains its ViewState.
Span values would not be saved after postback if you update them using Javascript. You should call server-side function to update span values or try to use Hidden fields to store your values.

Using FindControl to get GridView in a Content Page

I would like to find a GridView Control within a separate class and I am having issues doing so. I even tried placing my code in the aspx.cs page to no avail. I keep getting Object reference not set to an instance of an object. I'm sure there is a simple step I'm missing, but in my research I cannot seem to find anything.
Aspx code
<asp:GridView ID="GridView1" EnableViewState="true"
runat="server"
BackColor="White" BorderColor="#CC9966"
BorderStyle="None" BorderWidth="1px" CellPadding="4" Width="933px"
onrowdatabound="GridView1_RowDataBound"
onrowdeleting="GridView1_RowDeleting"
onrowediting="GridView1_RowEditing"
onrowupdating="GridView1_RowUpdating"
onsorting="GridView1_Sorting"
AllowSorting="true"
AutoGenerateColumns="False"
PersistedSelection="true" onrowcancelingedit="GridView1_RowCancelingEdit">
<EditRowStyle Font-Size="Small" Width="100px" />
<FooterStyle BackColor="#FFFFCC" ForeColor="#330099" />
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" ID="EditLinkButton" CausesValidation="True"
Text="Edit" CommandName="Edit"/>
<asp:LinkButton runat="server" ID="DeleteLinkButton" CausesValidation="False"
Text="Delete" CommandName="Delete"/>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton runat="server" ID="UpdateLinkButton" CausesValidation="True"
Text="Update" CommandName="Update"/>
<asp:LinkButton runat="server" ID="CancelLinkButton" CausesValidation="False"
Text="Cancel" CommandName="Cancel"/>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
.cs code
protected void Page_Load(object sender, EventArgs e) {
SetDirectory();
System.Web.UI.Page page = (System.Web.UI.Page)System.Web.HttpContext.Current.Handler;
GridView GridViewCopy = (GridView)page.FindControl("GridView1");
Log.WriteLine("SortBindGrid: GridView Row Count: " +
GridViewCopy.Rows.Count, Log.DEBUG_LEVEL.TERSE);
return;
}
I've tried a few variations of using MainContent_GridView for the find to get and Master.FindControl with all the same result.
In one of your comments you state that the GridView isn't on the Master Page, so is it safe to assume that it's on a page that uses a Master Page? And therefore it must be in a ContentPlaceholder control?
The key issue is that FindControl method only looks for direct children (emphasis added):
This method will find a control only if the control is directly contained by the specified container; that is, the method does not search throughout a hierarchy of controls within controls.
So you either need to:
Search for the control within the correct ContentPlaceholder control, rather than from Page.
Loop through each of the Controls in Page.Controls recursively until you find the control you're after.
An example of 2:
private Control FindControlRecursive(Control rootControl, string controlID)
{
if (rootControl.ID == controlID) return rootControl;
foreach (Control controlToSearch in rootControl.Controls)
{
Control controlToReturn =
FindControlRecursive(controlToSearch, controlID);
if (controlToReturn != null) return controlToReturn;
}
return null;
}
Once you've got your control, you should cast it using as and then check for null just in case it's not quite what you were expecting:
var gridView = FindControlRecursively(Page, "GridView1") as GridView
if (null != gridView) {
// Do Stuff
}
Don't get the page from HttpContext if you are already within the page. Instead, is there a control you can use FindControl from? Instead of use page, use:
parentControl.FindControl("GridView1") as GridView;
Instead. There is an issue with finding the grid from the page level, and using a lower level control closer to the grid will have better success.
Brian got it right but he forgot the essential part.
You won't be able to do use his code unless you add this code on top of your HTML-Code of the file where you want to use it.(Page.aspx)
<%# MasterType VirtualPath="~/Master/Site.master" %>
then you can use the code Brian suggested:
GridView grid = this.Master.FindControl("GridView1");
Edit:
If you want to use the gridview from within another class in the same file i would use the following:
Add this to the class created when you make the page
public partial class YourPageName: System.Web.UI.Page
{
public static Gridview mygrid = this.GridviewnameOFYourASPX
...
}
And to your custom class add this in your method
YourPageName.mygrid.(The changes you want to make);

ASP .Net Gridview bind to data only when clicking update

Here's how I want the control to work. Click edit on a row in gridview. There's a textbox in one of the columns, I would like it to be blank even though there's data in the database for that column, but when I click update I would like whatever new text the user entered to update the database for that column. It would be one-way databinding, but the other way?
Here's how I did it using an sql datasource with the select,update and delete methods generated.
First, you'll need to make any column that you want to edit like this a template field with an item template and and edit item template:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" DataSourceID="SqlDataSource1"
onrowupdating="GridView1_RowUpdating">
<Columns>
<asp:TemplateField HeaderText="City" SortExpression="City">
<ItemTemplate>
<asp:Label runat="server" Text='<%# Eval("City") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="txtCityEdit" Text=""></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Next handle the gridview's on update event:
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
//find the value control who's value you want
TextBox tb = (TextBox)GridView1.Rows[e.RowIndex].FindControl("txtCityEdit");
//since we are not using a bound column for city we need to explicitly insert the value
//into the update parameter.
SqlDataSource1.UpdateParameters["City"].DefaultValue = tb.Text;
}
Even if you are using something other than an SQL Datasource this should be the basic solution.
// Find notes textbox
TextBox tb = (TextBox)MyActiveReferrals.Rows[e.RowIndex].FindControl("NotesTextBox");
e.NewValues.Add("Notes", tb.Text);
I used a linq data source.

Resources