First Click on ASP.NET control does not fire on click event - c#

I'm seeing this behavior on two of my pages, but I'm just going to ask about the one that's more important to me at the moment. I have a page that loads information from a database into a ASP gridview and then allows the user to add a detail to each populated line.
The issue I'm having is that when the 'Edit' button of the gridview and then subsequently the 'Update' or 'Cancel' button, it takes two click to actually fire the onclick event. A post back does take place on the first click, but nothing actually happens.
I'm including the code that seems relevant below. The page uses a master page and there are a number of divs involved with formatting, I'm excluding those.
Gridview and related controls:
<asp:UpdatePanel runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label Text="Plant Selector: " runat="server" />
<asp:DropDownList ID="ddlPlant" OnSelectedIndexChanged="ddlPlant_SelectedIndexChanged" runat="server" />
<asp:Button ID="btnUpdate" Text="Update" OnClick="btnUpdate_Click" runat="server" />
<p />
<asp:Label ID="lblTest" Text="" runat="server" />
<asp:Label ID="lblerror" Text="" ForeColor="Red" runat="server" />
<asp:GridView ID="gridview1" AutoGenerateColumns="false" runat="server" OnRowEditing="gridview1_RowEditing" OnRowCancelingEdit="gridview1_RowCancelingEdit" OnRowUpdating="gridview1_RowUpdating">
<Columns>
<asp:BoundField DataField="JobNum" HeaderText="Job Number" ReadOnly="true" />
<asp:BoundField DataField="ModelNum" HeaderText="Model" ReadOnly="true" />
<asp:BoundField DataField="Customer" HeaderText="Customer" ReadOnly="true" />
<asp:BoundField DataField="SchCompDate" HeaderText="Sch Comp Date" ReadOnly="true" />
<asp:TemplateField HeaderText="Details">
<EditItemTemplate>
<asp:TextBox ID="Txt" Width="98%" runat="server" />
</EditItemTemplate>
<ItemTemplate>
<asp:Label Text="Click Edit to add details of exception." runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ShowEditButton="true" />
</Columns>
</asp:GridView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="gridview1" />
</Triggers>
</asp:UpdatePanel>
Sample image below:
Here is the code behind:
private string Plant { get; set; }
// This sets the default plant based off IP.
protected void Page_PreInit(Object sender, EventArgs e)
{
getPlantFromIP();
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
populateDDL();
BindData();
}
else
{
Plant = ddlPlant.SelectedValue.ToString();
}
}
// Populates the drop down.
private void populateDDL()
{
ddlPlant.Items.Add("NC");
ddlPlant.Items.Add("WA");
setPlantInDDL();
}
private void setPlantInDDL()
{
if(Plant == "WA")
{
ddlPlant.SelectedIndex = 1;
}
if (Plant == "NC")
{
ddlPlant.SelectedIndex = 0;
}
}
private void getPlantFromIP()
{
if (Request.ServerVariables["REMOTE_ADDR"] == "70.103.118.100")
{
Plant = "WA";
//ddlPlant.SelectedIndex = 1;
}
else
{
Plant = "NC";
//ddlPlant.SelectedIndex = 0;
}
}
// Database Query.
private DataTable getDataFromDatabase()
{
DataTable rTable = new DataTable();
string plant = ddlPlant.SelectedValue.ToString();
using (var conn = new MySqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["workorderConnectionString"].ConnectionString))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
try
{
cmd.CommandText = #"SELECT * FROM reportdatatables.compliance_exception_report
WHERE ExceptionNoted = '0' AND Plant = #plant";
cmd.Parameters.AddWithValue("#plant", plant);
MySqlDataReader reader = cmd.ExecuteReader();
rTable.Load(reader);
reader.Close();
cmd.Dispose();
}
catch
{
}
finally
{
conn.Close();
}
}
}
return rTable;
}
// Binds the data from the database to the gridview.
private void BindData()
{
DataTable data = getDataFromDatabase().Copy();
gridview1.DataSource = data;
gridview1.DataBind();
}
protected void ddlPlant_SelectedIndexChanged(object sender, EventArgs e)
{
//Plant = ddlPlant.SelectedValue.ToString();
BindData();
}
// On edit call.
protected void gridview1_RowEditing(object sender, GridViewEditEventArgs e)
{
}
// On cancel call.
protected void gridview1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
gridview1.EditIndex = -1;
}
protected void gridview1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
}
protected void btnUpdate_Click(object sender, EventArgs e)
{
BindData();
}
Here's what I've tried:
-A lot of posts a read saw this behavior relating to autopostback settings of controls. As you can see I'm made sure to not have any control with the autopostback set to true.
-I had some concern that the behavior might be related to the updatepanel, but removing it doesn't change the behavior at all.
-I read that having AutoEventWireup="true" in your page tag can cause this. I DO have that in my page tag, but setting it to false does not fix the issue and prevents my dropdown from being populated on page load.
-There was another post that suggested the ID of the control could be changing between page load and post back. I monitored the IDs of those controls and I do not see any change in their ID.
So all that being said, I'm hoping someone has a clue as to what I'm missing. If there is any more information I can provide that might help, please let me know.
Thank you in advance.

Try this, which will make the grid editable
protected void gridview1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
BindData();
}
for cancel also
protected void gridview1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
gridview1.EditIndex = -1;
BindData();
}

Related

asp.net Gridview checkbox - false value

I have read several other questions similar to this, and it looks to be a databinding issue. My issue somehow differs as I do not bind the data on page load. The data is bound when a selection is made from another table on the same page.
For example, my page has 3 tables (one with no value initially):
Sessions - Each session has a session date and a list of attendees
PlayersList - Contains records for all players
Attendees - Displays a list of players for a SELECTED session, from the Sessions table
Each time I select a session, and then check the Attendees checkbox, the value is always 'False'.
Thanks in advance
Here's my code.
Matches.aspx.cs
public partial class Matches : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void GridSessionsList_SelectedIndexChanged(object sender, EventArgs e)
{
}
protected void GridAttendees_SelectedIndexChanged(object sender, EventArgs e)
{
// this will remove an attendee from the list
}
protected void ButtonUpdatePaid_Click1(object sender, EventArgs e)
{
Session editSession = new Session();
foreach (GridViewRow row in GridAttendees.Rows)
{
editSession.Date = Convert.ToDateTime(GridSessionsList.SelectedValue);
int PlayerID = Convert.ToInt32(row.Cells[1].Text);
bool Paid = Convert.ToBoolean(row.FindControl("Chk") as TextBox);
editSession.UpdateAttendeeList(PlayerID, Paid);
}
}
protected void GridPlayersList_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
Session editSession = new Session();
editSession.Date = Convert.ToDateTime(GridSessionsList.SelectedValue);
int PlayerID = Convert.ToInt32(GridPlayersList.SelectedRow.Cells[1].Text);
editSession.UpdateAttendeeList(PlayerID);
GridAttendees.DataBind();
LabelError.Text = "Player has been added to the game on .";
}
catch
{
LabelError.Text = "Something went wrong.. Ensure you have a game selected.";
}
}
public void Chk_OnCheckedChanged(object sender, EventArgs e)
{
}
And here's the Attendees GridView extract from the aspx page:
<asp:GridView ID="GridAttendees" runat="server" AutoGenerateColumns="False" DataSourceID="SqlDataSource2" CssClass="Table" DataKeyNames="PlayerID" OnSelectedIndexChanged="GridAttendees_SelectedIndexChanged">
<Columns>
<asp:CommandField ShowSelectButton="True" SelectText="Select"/>
<asp:BoundField DataField="PlayerID" HeaderStyle-CssClass = "hideGridColumn" ItemStyle-CssClass="hideGridColumn" HeaderText="PlayerID" SortExpression="PlayerID" InsertVisible="False" ReadOnly="True" >
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="Chk" runat="server" OnCheckedChanged="Chk_OnCheckedChanged" AutoPostBack="True" Checked='<%# Bind("Paid") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle CssClass="TableHeader" />
<SelectedRowStyle BackColor="Silver" />
</asp:GridView>
I think you are casting your CheckBox as a TextBox ?
Here:
bool Paid = Convert.ToBoolean(row.FindControl("Chk") as TextBox);
Try this:
CheckBox cb = (CheckBox)row.FindControl("Chk");
bool Paid = cb.Checked;

Variables lost on postback in asp.net

I have a gridview with some data and I want to add a checkbox column which can choose multiple rows. By clicking on it I want to save an primary key of row and change css class of row.
Using this article(step 2) I created itemtemplate,added there a checkbox(specifying ID as TransactionSelector), and add a checkedChange() to it. There I only change a css class of row and add a row index to arraylist. But when I click button with event which show this list, it has no items.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" >
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="TransactionSelector" runat="server"
oncheckedchanged="TransactionSelector_CheckedChanged" AutoPostBack="True" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="iTransactionsId" HeaderText="iTransactionsId"
SortExpression="iTransactionsId" />
<asp:BoundField DataField="mAmount" HeaderText="mAmount"
SortExpression="mAmount" />
<asp:BoundField DataField="vchTransactionType" HeaderText="vchTransactionType"
SortExpression="vchTransactionType" />
<asp:BoundField DataField="dtDate" HeaderText="dtDate"
SortExpression="dtDate" />
<asp:BoundField DataField="cStatus" HeaderText="cStatus"
SortExpression="cStatus" />
<asp:BoundField DataField="test123" HeaderText="test123"
SortExpression="test123" />
</Columns>
<RowStyle CssClass="unselectedRow" />
</asp:GridView>
</asp:Panel>
<asp:Panel ID="InfoPanel" runat="server" CssClass="infoPanel">
<asp:Button ID="ShowSelected" runat="server" Text="Button"
onclick="ShowSelected_Click" />
<asp:Label ID="InfoLabel" runat="server"></asp:Label>
</asp:Panel>
C Sharp code:
public partial class WebForm1 : System.Web.UI.Page
{
ArrayList indices = new ArrayList();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GridView1.DataSourceID = "SqlDataSource1";
GridView1.DataBind();
}
}
protected void TransactionSelector_CheckedChanged(object sender, EventArgs e)
{
CheckBox cb = (CheckBox)sender;
GridViewRow row = (GridViewRow)cb.NamingContainer;
// row.CssClass = (cb.Checked) ? "selectedRow" : "unselectedRow";
if (cb.Checked)
{
row.CssClass = "selectedRow";
indices.Add(row.RowIndex);
}
else
{
row.CssClass = "unselectedRow";
indices.Remove(row.RowIndex);
}
}
protected void ShowSelected_Click(object sender, EventArgs e)
{
InfoLabel.Text = "";
foreach (int i in indices)
{
InfoLabel.Text += i.ToString() + "<br>";
}
}
}
}
You have to persist variable in postback using ViewState. Also its better if you use List<T> generic implementation rather than ArrayList
ViewState["Indices"] = indices;
And to recover it back
indices = ViewState["Indices"] as ArrayList;
As Habib said, you could use ViewState. You could also use ControlState instead, as shown here. If your code is in a custom control or user control, you may also need to override OnInit to
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Page.RegisterRequiresControlState(this);
}
Please feel free to respond with feedback. I'm new at posting answers.

Gridview with Enable and Disable image buttons

I have gridview in an asp.net application. I want to insert a column with image buttons where by click on it will enable or disable users or change the status field in db and also change the image button image accordingly user status.
Meaning: I want to display different images for disabled and enabled users.
How can I do this in C# and bind the data to the image button?
Anyone please help. Thanks in advance.
Make use of the ItemDataBound event. This is where you can check each row of your grid and apply changes to it. Then you can hide / unhide or change buttons:
VB.net below but you can easily convert to C#:
Dim ib As ImageButton = CType(e.Item.FindControl("ibFav"), ImageButton)
ib.Visible = False
Dim ib2 As ImageButton = CType(e.Item.FindControl("ibRemFav"), ImageButton)
ib2.Visible = True
Sample User Model:
public class UserModel {
public string Name { get; set; }
public bool IsEnabled { get; set; }
}
Here is the GridView Code:
<asp:GridView ID="GridView" runat="server" AutoGenerateColumns="false"
onrowcommand="GridView_RowCommand" onrowdatabound="GridView_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemStyle HorizontalAlign="Center" />
<ItemTemplate>
<asp:ImageButton ID="EnabledImgBtn" runat="server"
CommandArgument='<%# Eval("Name") %>'
CommandName="ResetUserState" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Name" HeaderText="Name" />
//Other columns....
</Columns>
</asp:GridView>
Set the 'CommandArgument' according to your needs. e.g the ID of the User.
Sample Code-behind for the gridview:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack){
LoadGridView();
}
}
private void LoadGridView()
{
this.GridView.DataSource = GetUsersFromDatabase();
this.GridView.DataBind();
}
protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var user = e.Row.DataItem as UserModel;
var enabledImgBtn = e.Row.FindControl("EnabledImgBtn") as ImageButton;
if (enabledImgBtn != null)
enabledImgBtn.ImageUrl = user.IsEnabled ? "~/YourImagePath/enabled.png"
: "~/YourImagePath/disalbed.png";
}
}
protected void GridView_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "ResetUserState")
{
if (e.CommandArgument!= null)
{
var userName = e.CommandArgument.ToString();
//Change user enabled state and Update database
//Sample code:
var user = FindUserByName("userName");
user.IsEnabled = !user.IsEnabled;
//SaveInDatabase(user);
LoadGridView();
}
}
}
You may consider using 'CommandField' with Type equal to 'Image' instead of 'TemplateField', but there is an issue with this approach, read more.
Hope this helps.
<asp:GridView ID="GridView" runat="server" AutoGenerateColumns="false"
onrowcommand="GridView_RowCommand" onrowdatabound="GridView_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="Change Status" ItemStyle-CssClass="GrdItemImg">
<ItemTemplate>
<asp:ImageButton ID="ibtnChangeActiveStatus" CommandArgument='<%#Eval("RecordID")%>'
CommandName='GRDSTATUS' runat="server" ImageUrl='<%# getStatusImage(Convert.ToInt32(DataBinder.Eval(Container.DataItem,"IsApproved"))) %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Col2" HeaderText="Col2" />
//Other Respective columns....
...........
..........
</Columns>
</asp:GridView>
And In CS file add the following function.
public string getStatusImage(int intStatus)
{
string strStatus = string.Empty;
if (intStatus == 1)
{
strStatus = "~/images/active.png";
}
else
{
strStatus = "~/images/inactive.png";
}
return strStatus;
}
So on the base of "intStatus" respective active / InActive Image will be set.

How to delete row in gridview using rowdeleting event?

This is my .cs code :
protected void Gridview1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
Gridview1.DeleteRow(e.RowIndex);
Gridview1.DataBind();
}
and this is markup,
<asp:gridview ID="Gridview1" runat="server" ShowFooter="true"
AutoGenerateColumns="false" OnRowDeleting="Gridview1_RowDeleting">
<Columns>
<asp:BoundField DataField="RowNumber" HeaderText="Row Number" />
<asp:TemplateField HeaderText="Column Name">
<ItemTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<%-- <asp:TemplateField HeaderText="Header 2">
<ItemTemplate>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>--%>
<asp:TemplateField HeaderText="Data Type">
<ItemTemplate>
<asp:DropDownList ID="ddldatatype" runat="server">
<asp:ListItem>varchar</asp:ListItem>
<asp:ListItem>int</asp:ListItem>
<asp:ListItem>numeric</asp:ListItem>
<asp:ListItem>uniqueidentifier</asp:ListItem>
<asp:ListItem>char</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
<FooterStyle HorizontalAlign="Right" />
<FooterTemplate>
<asp:Button ID="ButtonAdd" runat="server" Text="Add New Row" OnClick="ButtonAdd_Click"/>
<asp:Button ID="ButtonDel" runat="server" Text="Delete Row" OnClick="ButtonDel_Click" />
<input type="hidden" runat="server" value="0" id="hiddencount" />
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="lnkdelete" runat="server" CommandName="Delete" >Delete</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:gridview>
Please sugegest me. I have done this much.. but still not deleting row...
protected void Gridview1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
//Gridview1.DeleteRow((int)Gridview1.DataKeys[e.RowIndex].Value);
//Gridview1.DeleteRow(e.RowIndex);
//Gridview1.DataBind();
foreach(DataRow dr in dt.Rows)
{
dt.Rows.Remove(dr);
dt.Rows[e.RowIndex].Delete();
}
Gridview1.DeleteRow(e.RowIndex);
// dt = (DataTable)Gridview1.DataSource;
Gridview1.DataSource = dt;
Gridview1.DataBind();
}
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
GridViewRow row = (GridViewRow)GridView1.Rows[e.RowIndex];
SqlCommand cmd = new SqlCommand("Delete From userTable (userName,age,birthPLace)");
GridView1.DataBind();
}
Make sure to create a static DataTable object and then use the following code:
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
dt.Rows.RemoveAt(e.RowIndex);
GridView1.DataSource = dt;
GridView1.DataBind();
}
Try This Make sure You mention Datakeyname which is nothing but the column name (id) in your designer file
//your aspx code
<asp:GridView ID="dgUsers" runat="server" AutoGenerateSelectButton="True" OnDataBound="dgUsers_DataBound" OnRowDataBound="dgUsers_RowDataBound" OnSelectedIndexChanged="dgUsers_SelectedIndexChanged" AutoGenerateDeleteButton="True" OnRowDeleting="dgUsers_RowDeleting" DataKeyNames="id" OnRowCommand="dgUsers_RowCommand"></asp:GridView>
//Your aspx.cs Code
protected void dgUsers_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
int id = Convert.ToInt32(dgUsers.DataKeys[e.RowIndex].Value);
string query = "delete from users where id= '" + id + "'";
//your remaining delete code
}
Your delete code looks like this
Gridview1.DeleteRow(e.RowIndex);
Gridview1.DataBind();
When you call Gridview1.DataBind() you will populate your gridview with the current datasource. So, it will delete all the existent rows, and it will add all the rows from CustomersSqlDataSource.
What you need to do is delete the row from the table that CustomersSqlDataSource querying.
You can do this very easy by setting a delete command to CustomersSqlDataSource, add a delete parameter, and then execute the delete command.
CustomersSqlDataSource.DeleteCommand = "DELETE FROM Customer Where CustomerID=#CustomerID"; // Customer is the name of the table where you take your data from. Maybe you named it different
CustomersSqlDataSource.DeleteParameters.Add("CustomerID", Gridview1.DataKeys[e.RowIndex].Values["CustomerID"].ToString());
CustomersSqlDataSource.Delete();
Gridview1.DataBind();
But take into account that this will delete the data from the database.
The easiest way is to create your GridView with some data source in ASP and call that data source in Row_Deletinng Event. For example if you have SqlDataSource1 as your GridView data source, your Row_Deleting event would be:
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
int ID = int.Parse(GridView1.Rows[e.RowIndex].FindControl("ID").toString());
string delete_command = "DELETE FROM your_table WHERE ID = " + ID;
SqlDataSource1.DeleteCommand = delete_command;
}
See the following code and make some changes to get the answer for your question
<%# Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void CustomersGridView_RowDeleting
(Object sender, GridViewDeleteEventArgs e)
{
TableCell cell = CustomersGridView.Rows[e.RowIndex].Cells[2];
if (cell.Text == "Beaver")
{
e.Cancel = true;
Message.Text = "You cannot delete customer Beaver.";
}
else
{
Message.Text = "";
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>GridView RowDeleting Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>
GridView RowDeleting Example
</h3>
<asp:Label ID="Message" ForeColor="Red" runat="server" />
<br />
<asp:GridView ID="CustomersGridView" runat="server"
DataSourceID="CustomersSqlDataSource"
AutoGenerateColumns="False"
AutoGenerateDeleteButton="True"
OnRowDeleting="CustomersGridView_RowDeleting"
DataKeyNames="CustomerID,AddressID">
<Columns>
<asp:BoundField DataField="FirstName"
HeaderText="FirstName" SortExpression="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName"
SortExpression="LastName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="StateProvince" HeaderText="State"
SortExpression="StateProvince" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="CustomersSqlDataSource" runat="server"
SelectCommand="SELECT SalesLT.CustomerAddress.CustomerID,
SalesLT.CustomerAddress.AddressID,
SalesLT.Customer.FirstName,
SalesLT.Customer.LastName,
SalesLT.Address.City,
SalesLT.Address.StateProvince
FROM SalesLT.Customer
INNER JOIN SalesLT.CustomerAddress
ON SalesLT.Customer.CustomerID =
SalesLT.CustomerAddress.CustomerID
INNER JOIN SalesLT.Address ON SalesLT.CustomerAddress.AddressID =
SalesLT.Address.AddressID"
DeleteCommand="Delete from SalesLT.CustomerAddress where CustomerID =
#CustomerID and AddressID = #AddressID"
ConnectionString="<%$ ConnectionStrings:AdventureWorksLTConnectionString %>">
<DeleteParameters>
<asp:Parameter Name="AddressID" />
<asp:Parameter Name="CustomerID" />
</DeleteParameters>
</asp:SqlDataSource>
</form>
</body>
</html>
In Grid use this code having ID as your Primary Element so to uniquely identify each ROW
<asp:TemplateField>
<ItemTemplate>
<asp:HiddenField ID="Hf_ID" runat="server" Value='<%# Eval("ID") %>' />
</ItemTemplate>
</asp:TemplateField>
and to search the uique ID use the code in C# code behind (basically this is searching hidden field and storing it in a var)
protected void Grd_Registration_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
var ID = (HiddenField)Grd_Registration.Rows[e.RowIndex].FindControl("ID");
//Your Delete Logic Goes here having ID to delete
GridBind();
}
The solution is somewhat simple; once you have deleted the row from the datagrid (Your code ONLY removes the row from the grid and NOT the datasource) then you do not need to do anything else.
As you are doing a databind operation immediately after, without updating the datasource, you are re-adding all the rows from the source to the gridview control (including the row removed from the grid in the previous statement).
To simply delete from the grid without a datasource then just call the delete operation on the grid and that is all you need to do... no databinding is needed after that.
Add the below line in Page load,
ViewState["GetRecords"] = dt;
then try this,
protected void DeleteRows(object sender, GridViewDeleteEventArgs e)
{
dt = ViewState["GetRecords"] as DataTable;
dt.Rows.RemoveAt(e.RowIndex);
dt.AcceptChanges();
ViewState["GetRecords"] = dt;
BindData();
}
If you Still have any problem, send the code in BindData() method
I think you are doing same mistake of rebinding as mentioned in this link
How to delete row from gridview?
If I remember from your previous questions, you're binding to a DataTable. Try this:
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
DataTable sourceData = (DataTable)GridView1.DataSource;
sourceData.Rows[e.RowIndex].Delete();
GridVie1.DataSource = sourceData;
GridView1.DataBind();
}
Essentially, as I said in my comment, grab a copy of the GridView's DataSource, remove the row from it, then set the DataSource to the updated object and call DataBind() on it again.
Here is a trick with what you want to achieve. I was also having problem like you.
Its hard to get selected row and data key in RowDeleting Event But it is very easy to get selected row and datakeys in SelectedIndexChanged event. Here's an example-
protected void gv_SelectedIndexChanged(object sender, EventArgs e)
{
int index = gv.SelectedIndex;
int vehicleId = Convert.ToInt32(gv.DataKeys[index].Value);
SqlConnection con = new SqlConnection("-----");
SqlCommand com = new SqlCommand("DELETE FROM tbl WHERE vId = #vId", con);
com.Parameters.AddWithValue("#vId", vehicleId);
con.Open();
com.ExecuteNonQuery();
}
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
int index = GridView1.SelectedIndex;
int id = Convert.ToInt32(GridView1.DataKeys[index].Value);
SqlConnection con = new SqlConnection(str);
SqlCommand com = new SqlCommand("spDelete", con);
com.Parameters.AddWithValue("#PatientId", id);
con.Open();
com.ExecuteNonQuery();
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
I know this is a late answer but still it would help someone in need of a solution.
I recommend to use OnRowCommand for delete operation along with DataKeyNames, keep OnRowDeleting function to avoid exception.
<asp:gridview ID="Gridview1" runat="server" ShowFooter="true"
AutoGenerateColumns="false" OnRowDeleting="Gridview1_RowDeleting" OnRowCommand="Gridview1_RowCommand" DataKeyNames="ID">
Include DataKeyNames="ID" in the gridView and specify the same in link button.
<asp:LinkButton ID="lnkdelete" runat="server" CommandName="Delete" CommandArgument='<%#Eval("ID")%>'>Delete</asp:LinkButton>
protected void Gridview1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
int ID = Convert.ToInt32(e.CommandArgument);
//now perform the delete operation using ID value
}
}
protected void Gridview1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
//Leave it blank
}
If this is helpful, give me +
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
MySqlCommand cmd;
string id1 = GridView1.DataKeys[e.RowIndex].Value.ToString();
con.Open();
cmd = new MySqlCommand("delete from tableName where refno='" + id1 + "'", con);
cmd.ExecuteNonQuery();
con.Close();
BindView();
}
private void BindView()
{
GridView1.DataSource = ms.dTable("select * from table_name");
GridView1.DataBind();
}
//message box before deletion
protected void grdEmployee_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
foreach (DataControlFieldCell cell in e.Row.Cells)
{
foreach (Control control in cell.Controls)
{
LinkButton button = control as LinkButton;
if (button != null && button.CommandName == "Delete")
button.OnClientClick = "if (!confirm('Are you sure " +
"you want to delete this record?')) return false;";
}
}
}
}
//deletion
protected void grdEmployee_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
conn.Open();
int empid = Convert.ToInt32(((Label)grdEmployee.Rows[e.RowIndex].Cells[0].FindControl("lblIdBind")).Text);
SqlCommand cmdDelete = new SqlCommand("Delete from employee_details where id=" + empid, conn);
cmdDelete.ExecuteNonQuery();
conn.Close();
grdEmployee_refreshdata();
}

ASP.NET GridView, enabling/disabling buttons after paging

I have successfully implemented my GridView now, but, as always, the whole ASP.NET life cycle thing is bothering me. I can't figure out why this doesn't work. I have bound the GridView's OnPageIndexChanged as such:
protected void GridView_PageIndexChanged(object sender, EventArgs e)
{
// Enable/disable the previous/next buttons.
LinkButton btnNextPage = (LinkButton)gvTable.BottomPagerRow.FindControl("btnNextPage");
LinkButton btnPreviousPage = (LinkButton)gvTable.BottomPagerRow.FindControl("btnPreviousPage");
btnNextPage.Enabled = false;
btnPreviousPage.Enabled = false;
}
This is my ASCX:
<asp:GridView ID="gvTable" runat="server" ShowHeader="true" PageSize="1"
AllowPaging="true" AllowSorting="true" DataSourceID="dsLinqActivities"
AutoGenerateColumns="false" OnRowDataBound="GridView_DataBound"
OnPageIndexChanged="GridView_PageIndexChanged">
<Columns>
<asp:BoundField DataField="Edited" HeaderText="Date" />
<asp:BoundField DataField="Status" HeaderText="Status" />
<asp:BoundField DataField="Activity" />
</Columns>
<PagerSettings Position="Bottom" Visible="true" />
<PagerStyle CssClass="pager" />
<PagerTemplate>
<asp:LinkButton ID="btnPreviousPage" class="navbtn prev left"
runat="server" CommandName="Page" CommandArgument="Prev">
<span>Newer activities</span></asp:LinkButton>
<asp:LinkButton ID="btnNextPage" class="navbtn next right"
runat="server" CommandName="Page" CommandArgument="Next">
<span>Older activities</span></asp:LinkButton>
</PagerTemplate>
</asp:GridView>
I debug my application and see that the code is being run and does the right thing but for some reason when the control is rendered, both of the buttons are always enabled. What am I doing wrong here?
If I were you, I would code it like this in the "GridView_PageIndexChanged" method
(gvTable.BottomPagerRow.FindControl("btnNextPage") as LinkButton).Enabled = true/false;
Edit:Can you also try adding a setter ?
set
{
gvTable.BottomPagerRow.FindControl("btnNextPage") as LinkButton =value;
}
Edit: OK my friend, I finally worked out a solution. May be not very elegant,but it works and I tested it. There are a few things to take care of:
1. We are having a "Prev" and a "Next" button and we got to handle "OnCommand" events for those since we are using our own Pager Template
2. We would have to bind data after we handle our OnCommand event.
I have a static List<String> which I populated during GET with random strings (Courtesy: http://www.kivela.be/index.php/2007/06/19/how-to-generate-a-random-string-in-c-20/) and bound them to my grid. You can substitute your own datasource here.Also, we have to change the grid's page index manually in our OnCommand Event.
Here is my aspx/ascx grid
<asp:GridView ID="GridView1" runat="server" OnRowDataBound="GridView_DataBound"
AllowPaging="true" PagerSettings-Mode="NextPrevious" PagerSettings-Position="Bottom" PageSize="10"
OnPageIndexChanged="GridView_PageIndexChanged">
<PagerSettings Position="Bottom" Visible="true" />
<PagerStyle CssClass="pager" />
<PagerTemplate>
<asp:LinkButton ID="btnPreviousPage" OnCommand="ChangePage"
runat="server" CommandName="Prev" Text="prev">
</asp:LinkButton>
<asp:LinkButton ID="btnNextPage" OnCommand="ChangePage"
runat="server" CommandName="Next" Text="next">
</asp:LinkButton>
</PagerTemplate>
</asp:GridView>
and here is the codebehind
public partial class TestPage : System.Web.UI.Page
{
private static Random _random = new Random();
static List<string> lst = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
for (int i = 1; i <= 30; i++)
{
lst.Add(RandomString(i));
}
GridView1.DataSource = lst;
GridView1.DataBind();
SetPageNumbers();
}
}
private void SetPageNumbers()
{
if (GridView1.PageIndex == 0)
{
(GridView1.BottomPagerRow.FindControl("btnPreviousPage")as LinkButton).Enabled = false;
}
if(GridView1.PageIndex ==GridView1.PageCount-1)
{
(GridView1.BottomPagerRow.FindControl("btnNextPage") as LinkButton).Enabled = false;
}
}
protected void ChangePage(object sender, CommandEventArgs e)
{
switch (e.CommandName)
{
case "Prev":
GridView1.PageIndex = GridView1.PageIndex - 1;
break;
case "Next":
GridView1.PageIndex = GridView1.PageIndex + 1;
break;
}
GridView1.DataSource = lst;
GridView1.DataBind();
SetPageNumbers();
}
public static string RandomString(int size)
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < size; i++)
{
//26 letters in the alfabet, ascii + 65 for the capital letters
builder.Append(Convert.ToChar(Convert.ToInt32(Math.Floor(26 * _random.NextDouble() + 65))));
}
return builder.ToString();
}
}
Hope this helps
Is there any chance your CSS is setting the enabled property?
I duplicated your code without the CSS and it works fine for me.
How about posting your css?

Categories

Resources