gridview findcontrol returning nothing empty string(Blank) - c#

I am trying to pass a session value from a gridview select row using GridView1_RowEditing1 event. i am able to get session value for primarykey (p.key) but the Associate_ID returns empty.
C# Code behind
protected void GridView1_RowEditing1(object sender, GridViewEditEventArgs e)
{
int primarykey = Convert.ToInt32(GridView1.DataKeys[e.NewEditIndex].Value);
string name = Convert.ToString(GridView1.Rows[e.NewEditIndex].FindControl("Associate_ID"));
Session["Number"] = primarykey;
Session["Name"] = name;
//redirect
Response.Redirect("updatee.aspx");
}
.ASPX
<asp:TemplateField HeaderText="Associate_ID" SortExpression="Associate_ID">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("Associate_ID") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("Associate_ID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
OUTPUT:
Key: 5
Name:
As you can see i am not getting Associate_ID for selected field.
Also tried using
string name = Convert.ToString(GridView1.Rows[3].Cells[3].FindControl("Associate_ID"));
but there was no result, the grid has multiple columns and rows (8*15)
tried suggestions on gridview findcontrol returning empty "" and tried stopping re-binding the GridView on the PostBack.
removed DataSourceID from gridview
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" OnRowEditing="GridView1_RowEditing1" OnSelectedIndexChanged="GridView1_SelectedIndexChanged">
code behind
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//DataSourceID = "SqlDataSource1"
GridView1.DataSource = SqlDataSource1;
GridView1.DataBind();
}
}
None of this helped. I am still getting a blank value for Associate_ID.
i am unable to see where the issue is. Please help!

You are trying to find the Control Associate_ID with FindControl. But it does not exist. Either find TextBox1 or rename the TextBox to Associate_ID.
<EditItemTemplate>
<asp:TextBox ID="Associate_ID" runat="server" Text='<%# Bind("Associate_ID") %>'></asp:TextBox>
</EditItemTemplate>
//or
string name = Convert.ToString(GridView1.Rows[3].Cells[3].FindControl("TextBox1"));
UPDATE
I see the problem, somehow you are trying to access those control before the edit state has been activated by rebinding the GridView. The edit index has not been set. So place this before the FindControl.
GridView1.DataSource = yourSource;
GridView1.EditIndex = e.NewEditIndex;
GridView1.DataBind();

Thank you so much VDWWD, i was finally able to get it to work.
The problem was i was not able to use get my 'TextBox' element in gridview using FindControl.
The solution was to not re-binding the GridView on the PostBack of the page and edit index on the RowEditing event.
This is what my working code looks like, is any one ever comes across a similar issue
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GridView1.DataSource = SqlDataSource1;
GridView1.DataBind();
}
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.DataSource = SqlDataSource1;
GridView1.EditIndex = e.NewEditIndex;
GridView1.DataBind();
TextBox txt = GridView1.Rows[e.NewEditIndex].FindControl("TextBox1") as TextBox;
string name = txt.Text;
}
.ASPX
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("CountryName") %>'></asp:TextBox>
</EditItemTemplate>

Related

Asp.Net C# Delete row from dataTable gridview on button click

I'm displaying a datatable that selects a number of elements from the database (IncomingsId, Type, Cost, Frequency) and I'm not sure how to delete a row when a button is clicked.
I've tried many solutions so far but nothing is working.
Here is the button I have within my Grid view
<asp:TemplateField HeaderText="Delete">
<ItemTemplate>
<asp:button id="DeleteRowButton" text="Delete Record" onclick="DeleteRowButton_Click" runat="server"/>
</ItemTemplate>
</asp:TemplateField>
And here is the code behind this page were I am creating the datatable.
SqlConnection con;
public _Default()
{
con = new SqlConnection(#"MySQLConnection");
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DisplayRecord();
}
}
public DataTable DisplayRecord()
{
string userId = (HttpContext.Current.User.Identity.GetUserId());
SqlDataAdapter Adp = new SqlDataAdapter("select * from Incomings where AspNetUsersId = '" + userId +"'", con);
DataTable Dt = new DataTable();
Dt.AcceptChanges();
Adp.Fill(Dt);
grid1.DataSource = Dt;
grid1.DataBind();
return Dt;
}
public void DeleteRowButton_Click(object sender, EventArgs e)
{
}
Cheers in advance for any help. I'm sure it's a simple resolution
You need a way for your code to know which ID to delete. Here is how I would normally do it:
Replace your button with an ItemTemplate, and add the button in here instead:
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Button Text="Delete" runat="server" CommandArgument='<%# Eval("userId") %>' CommandName="Delete" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
When you have the button this way, you now have access to a CommandArgument and CommandName attributes. Notice the argument I am passing is Eval("userId"), the command name (as you will see later) is used to recognize what action you want to execute (this could be anything, is just a name).
Replace the CommandArgument with whatever value(s) you want to pass to the server, using the name that came from the database/datasource (I am guessing it would be userId).
Then, to capture this you need to implement the RowCommand event of the GridView, and intercept the correct CommandName:
public void GridView1_RowCommand(Object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
string userId = e.CommandArgument.ToString();
//do something with the id
}
}
Here you have to make sure the CommandName in your button, matches to whatever action you want to execute in the RowCommand. This should do the trick.
Don't forget to bind the event to your GridView:
<asp:GridView OnRowCommand="GridView1_RowCommand" ID="GridView1" runat="server">
...
</asp:GridView>
just use this for the front-end code
<asp:GridView ID="grid1" OnRowDeleting="OnRowDeleting" DataKeyNames="deleteR" runat="server" AutoGenerateColumns="False" CellPadding="4" GridLines="None" style="width:100%" >
<columns>
<asp:TemplateField HeaderText="Delete Row">
<ItemTemplate>
<asp:Button ID="btnDelete" runat="server" class="btn btn-primary" Text="Delete" CommandName="Delete" OnRowDataBound="OnRowDataBound" />
</ItemTemplate>
</asp:TemplateField>
And have this in behind it:
protected void OnRowDeleting(object sender, GridViewDeleteEventArgs e)
{
int deleteR= Convert.ToInt32(grid1.DataKeys[e.RowIndex].Values[0]);
//have a sql statement here that add's the parameter ID for the row you want to delete, something like
SqlCommand com = new SqlCommand ("Delete FROM yourdatabase Where yourID = #yourID"
com.Parameters.AddWithValue("#yourID", yourID)
}
What you're looking for is indeed a simple solution.
You can use a foreach loop to search all DataRows within the DataTable for some kind of ID.Here's an example of what I mean:
String s = "/* IncomingsId for what you want to delete */";
foreach (DataRow r in dt.Rows) {
if (r["IncomingsId"].ToString().Equals(s)) {
dt.Rows.Remove(r);
}
}
Just a quick update for anyone that's helped me, thanks for your advice.
Asp.Net has it's own built in AutoGenerateDeleteButton and I set that to true and ran a bit of code behind it.
A simple solution that really shouldn't have taken me all day to complete!

Drop-down Selected Value not Showing in my Detailview

I have drop-down that is not showing the previoiusly selected value in my Detailview. It always shows me the first value in the list. If the previously selected value was xyz then when the Detailvies loads, i want to show xyz. I have researched a lot but could not find any solution that i can use. please help
here is my aspx code for the field that has the dropdown
<asp:TemplateField HeaderText="Name:">
<ItemTemplate>
<asp:Label ID="lbl_UID" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.Name") %>'></asp:Label></ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ddl_Name" Width="200px" Height="25" DataSourceID="SDS_Manager" DataTextField="FULL_NM" AutoPostBack="false"
DataValueField="UID" runat="server" AppendDataBoundItems="false">
<asp:ListItem Text="Select Name" Value="Select Name"></asp:ListItem>
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
here is the code behind that binds the detailview
protected void Edit(object sender, EventArgs e)
{
using (GridViewRow row = (GridViewRow)((LinkButton)sender).Parent.Parent)
{
sqlcon.Open();
sqlcmd = new SqlCommand(#"Select PRJ_ID, WPC_CD, WPC_DESC, Name FROM myTable where PRJ_ID = '" + myvar + "' ", sqlcon);
da = new SqlDataAdapter(sqlcmd);
da.Fill(dt);
sqlcon.Close();
DV_Edit.DataSource = dt;
DV_Edit.DataBind();
sqlcon.Close();
popup.Show();
}
}
Try setting AutoPostBack="true" and make sure if you have any logic to set the value of the drop down in the page load, that the code is not executed on post back as shown below.
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
ddlOne.DataSource = //your data here;
ddlOne.DataBind();
}
}
//if you don't wrap this logic in the if(!IsPostBack), the code will simply re-populate
//the drop down and set the selected index to the first item in the list with each
//post back.

GridView row won't disable

I am trying to disable a specific grdview row using the code below, but it isn't disabling that row. I am 100% sure there is a value called "Total Expenses" in the column that is bound to the gridview. What is more strange is that, I removed the if condition(accountTextBox.Text == "Total Expenses") to see if all the rows get disabled but only the first row is getting disabled. Any thoughts on this?
More information: Am using gridview with template fields(ASP.NET, C#). I also ran debugger and found that the accountTextBox is showing NULL. Am puzzled!
I appreciate any thoughts you may have. Thank you
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
if (!tableCopied)
{
originalDataTable = ((System.Data.DataRowView)e.Row.DataItem).Row.Table.Copy();
ViewState["originalValuesDataTable"] = originalDataTable;
tableCopied = true;
TextBox accountTextBox = (TextBox)e.Row.FindControl("AccountTextBox");
if (accountTextBox.Text == "Total Expenses")
{
e.Row.Enabled = false;
}
}
}
I'm assuming your markup looks something like this:
<asp:TemplateField HeaderText="SomeField" SortExpression="SomeField">
<EditItemTemplate>
<asp:TextBox ID="AccountTextBox" runat="server" Text='<%# Bind("SomeField") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("SomeField") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
In which case AccountTextBox will only be available in RowDataBound when e.Row.State is in Edit mode. which may or may not be available depending what update functionality is provided in your datasource...but that's something else.
Typically you don't use a TextBox to display data but lets say trying to populate a "readonly" TextBox then all you need do is move AccountTextBox from the EditTemplate to the ItemTemplate and you should be good to go.
Using the following code-behind:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
gvTest.DataSource = new List<string>() { "test1", "test2" };
gvTest.DataBind();
}
private bool tableCopied = false;
private System.Data.DataTable originalDataTable;
protected void gvTest_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
if (!tableCopied)
{
//originalDataTable = ((System.Data.DataRowView)e.Row.DataItem).Row.Table.Copy();
//ViewState["originalValuesDataTable"] = originalDataTable;
//tableCopied = true;
TextBox accountTextBox = (TextBox)e.Row.FindControl("AccountTextBox");
if (accountTextBox.Text == "Total Expenses")
{
e.Row.Enabled = false;
}
}
}
}
And this markup:
<asp:GridView runat="server" ID="gvTest" OnRowDataBound="gvTest_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="AccountTextBox" runat="server">Total Expenses</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I am not reproducing the bug. Both rows disable for me.
The tableCopied variable could be the problem. It will be set to true on the first row and this will restrict the remaining rows to enter the if condition and actually be disabled.
First row:
//tableCopied is false
if(!tableCopied) // pass
tableCopied = true
Other rows:
//tableCopied is true
if(!tableCopied) // wont pass
Note that the GridView1_RowDataBound event occurs once for every row on the same postback and every class member is persisted during the postback.

Can not find a control using the FindControl on RowCreated for Gridview

I am using a gridview, and here is one of my templatefields:
<asp:TemplateField HeaderText="Quantity" SortExpression="Quantity">
<HeaderTemplate>
<asp:Label ToolTip="Quantity" runat="server" Text="Qty"></asp:Label>
</HeaderTemplate>
<EditItemTemplate>
<asp:TextBox ID="txt_Quantity" runat="server" Text='<%# Bind("Quantity") %>' Width="30px"
Enabled='True'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
I am tring to reach txt_Quantity like this
protected void begv_OrderDetail_RowCreated(object sender, GridViewRowEventArgs e)
{
TextBox txt_Quantity = (TextBox)e.Row.FindControl("txt_Quantity");
txt_Quantity.Attributes.Add("onFocus", "test(this)");
}
This is the error message:
System.NullReferenceException: Object reference not set to an instance
of an object.
RowCreated is executed for every RowType(btw, the same as with RowDataBound), so for the header, data-row, footer or pager.
The first row is the header-row, but the TextBox is in rows with RowType=DataRow. Since it's in the EditItemTemplate you also have to check the EditIndex:
protected void begv_OrderDetail_RowCreated(object sender, GridViewRowEventArgs e)
{
if (row.RowType == DataControlRowType.DataRow
&& e.Row.RowIndex == begv_OrderDetail.EditIndex)
{
TextBox txt_Quantity = (TextBox)e.Row.FindControl("txt_Quantity");
txt_Quantity.Attributes.Add("onFocus", "test(this)");
}
}
Note that if you enumerate the Rows property of the GridView you only get the rows with RowType=DataRow, so the header, footer and pager are omitted. So here no additional check is needed:
foreach(GridViewRow row in begv_OrderDetail.Rows)
{
// only DataRows
}

GridView Conditional Button Visibility

I have this itemtemplate for a gridview column that is pulling data from a SQL database. My Question is how would I perform a check to see if my field ActivityFile has a value (which means a file is in the db) and then display the LinkButton at which point I generate code to download the file (already done and works).
<ItemTemplate>
<asp:LinkButton ID="DownloadFileBtn" runat="server" visible="false">Download File</asp:LinkButton>
<br />
<asp:Label ID="Label4" runat="server" Text='<%# Bind("ActivityLink") %>'></asp:Label>
</ItemTemplate>
you have to use GridView RowDataBound Event for that
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
System.Data.DataRowView dr = (System.Data.DataRowView)e.Row.DataItem;
if (Convert.ToBoolean(dr["columnName"].ToString()))
{
LinkButton LinkButton = (LinkButton)e.Row.Findcontrol("LinkButton");
LinkButton.Visible = false;
}
}
}

Categories