C# - Gridview Help. (ASP.NET) - c#

I have a gridview that pulls data from local SQL server. I chose 3 columns to be displayed on the gridview. I added a fourth column (select command). I would like to get the data from the first column which is an id when I click the select command but i always get an error "An exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll but was not handled in user code Additional information: Index was out of range. Must be non-negative and less than the size of the collection."
Basically I would like to get the id from the first column then assign it to a session variable then redirect to a second page and then use the content of that session variable to populate another textbox.
protected void grdClients_RowCommand(object sender, GridViewCommandEventArgs e)
{
string id = grdClients.Rows[grdClients.SelectedIndex].Cells[0].Text.ToString();
Session["ID"] = id;
Response.Redirect("secondPage.aspx");
}
Any suggestions?
Thanks

1- add attribute to the GridView
DataKeyNames="aboutusID"
2- add a templatefield to your columns
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CommandName="SelectSession" Text="EDIT" CommandArgument='<%# DataBinder.Eval(Container,"RowIndex")%>' ></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
3- in your code behind
protected void GridViewAbout_RowCommand(object sender, GridViewCommandEventArgs e)
{
// this to skip on paging or sorting command
if (e.CommandName != "Sort" & e.CommandName != "Page")
{
// Get the command argument where the index of the clicked button is stored
int index = Convert.ToInt32(e.CommandArgument);
// Get the data key of the index where the id is stored
int id = Convert.ToInt32(GridViewAbout.DataKeys[index].Value);
if (e.CommandName == "SelectSession")
{
// Your Code
}
}
}

i think you should use the SelectedIndexChanged event for that.
Then you assign the GridviewRow property to the selected row "GridViewRow row = grdClients.SelectedRow;"
After that you can use row to get the value of the first cell and assign it to your session or where ever you want. "row.Cells[0].Text;"
protected void grdClients_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow row = grdClients.SelectedRow;
string id = row.Cells[0].Text;
Session["ID"] = id;
Response.Redirect("secondPage.aspx");
}

Thank you everyone,
I was able to come up with a solution by taking pieces from every solution you provided. Thanks very much.
Below is my solution:
protected void grdClients_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Select")
{
int index = Convert.ToInt32(e.CommandArgument);
string id = grdClients.Rows[index].Cells[0].Text.ToString();
Session["ID"] = id;
Response.Redirect("secondForm.aspx");
}
}

Related

asp.net: How to update data in GridView through Checkbox in particular row

I am developing a Web Form, where I show Gridview with data. One of the column consists of CheckBox. How can I update data in particular row.
so my question is:
How to unidentified particular row and send an sql request with UPDATE when user Check or Uncheck the CheckBox?
Update:
Here is my code that i have. It doesn't update value of CheckBox.
namespace:
public partial class Call_Bills : System.Web.UI.Page
{
SqlConnection con = new SqlConnection();
string check;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button_Submit(object sender, EventArgs e)
{
foreach (GridViewRow row in GridView2.Rows)
{
con.ConnectionString = ConfigurationManager.ConnectionStrings["TestDeductionsConnectionString2"].ToString();
con.Open();
bool private1 = (row.FindControl("CheckBox1") as CheckBox).Checked;
if (private1 == true)
{
check = "1";
}
else
{
check = "0";
}
SqlCommand cmd = new SqlCommand("insert into DetailCosts(private) values(#private)", con);
cmd.Parameters.AddWithValue("#private", check);
cmd.ExecuteNonQuery();
}}
name of GridView is: GridView2;
name of Checkbox in the Table: private;
id of CheckBox in Gridview is:
<asp:TemplateField HeaderText="Private" SortExpression="private">
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server" Checked='<%# Eval("private") %>' />
</ItemTemplate>
<HeaderStyle HorizontalAlign="Center" />
</asp:TemplateField>
you can manually define a method to handle a postback generated by a control inside a gridview column. To do that you just need to add the tags AutoPostBack=True and OnCheckedChanged=YourMethodName to the control.
On the code-behind, define this method as public void, and define the parameters that usually would be there (sender as object and e as EventArgs), like:
public void YourMethodName(object sender, EventArgs e)
On the method, you may need to get the GridViewRow which contains the control that has generated the event. To do that, just parse the sender parameter (which will be the checkbox) and get 2 parent levels (GridViewCell and GridViewRow), it would be something like:
GridViewRow row = ((CheckBox)sender).parent.parent;
Since you have the row, you may get any control inside it with the FindControl method. If you need an id to identify the entitiy being updated, you may store it in a hidden field inside the row.
Hope it helps!

Get a hidden field in Gridview on RowCommand Event

If I have two buttons on gridview and each performing different function. For example my code below,
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Select")
{
//Do something else
}
else if (e.CommandName == "View Cert")
{
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow row = GridView1.Rows[index];
errorlab.Text = row.Cells[3].Text;
}
}
The value of cell 3 is a hidden field and there is a value in the database that's binding to hidden field but with my code I couldn't get the value. The errorlab label is showing nothing. Maybe I'm missing something.
I would like to suggest an answer, the command argument will not fetch you the row index. Instead it will give you what you bind during gridview data binding.
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Select")
{
//Do something else
}
else if (e.CommandName == "View Cert")
{
//The hidden field id is hdnProgramId
HiddenField hdnProgramId = (((e.CommandSource as LinkButton).Parent.FindControl("hdnProgramId")) as HiddenField);
}
}
This will try to locate the hidden field from the gridview row context.
If you have futher controls on the gridview cell then you have to access them using the Controls property
HiddenField hiddenField =row.Cells[3].Controls[0] as HiddenField;
if(hiddenField != null)
errorlab.Text = hiddenField.Value;
You have to use the correct index for the controls. Debug the code and check what is position of the control in row.Cells[3].Controls.
Always try to avoid referring cells by it's index position in gridview as it may result in changing the code if you happen to add/delete few more columns in the grid in the future which might result in undesired result. Also note that hiddenfield does not have a Text property but rather a Value property to access it's value.
If you know the hiddenfield's name then better try accessing it by it's name. Let's say you have your hiddenfield defined as below in your gridview
<ItemTemplate>
<asp:HiddenField ID ="hdnField" runat="server" Value='<%# Bind("ErrorLab") %>'/>
</ItemTemplate>
Then in your GridView1_RowCommand you can do
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow row = GridView1.Rows[index];
HiddenField hdnField = (HiddenField)row.FindControl("hdnField");
errorlab.Text = hdnField.Value;

Get Row Index on Asp.net Rowcommand event

I have an asp.net GridView:
<asp:TemplateField HeaderText="View Faktor" ShowHeader="False" Visible="True">
<ItemTemplate>
<asp:ImageButton ID="imgBtn1" CssClass="SelectRow" runat="server" CausesValidation="false"
CommandArgument='<%#(eval("mprID")) %>' CommandName="ViewFactors" ImageUrl="~/tadarokat/Images/factor.png"
Text="" />
</ItemTemplate>
</asp:TemplateField>
How Can I get rowIndex on row command event?
I want to highlight (select) target row when RowCommand fires.
this is answer for your question.
GridViewRow gvr = (GridViewRow)((ImageButton)e.CommandSource).NamingContainer;
int RowIndex = gvr.RowIndex;
ImageButton \ Button etc.
CommandArgument='<%# Container.DataItemIndex%>'
code-behind
protected void gvProductsList_RowCommand(object sender, GridViewCommandEventArgs e)
{
int index = e.CommandArgument;
}
Or, you can use a control class instead of their types:
GridViewRow row = (GridViewRow)(((Control)e.CommandSource).NamingContainer);
int RowIndex = row.RowIndex;
If you have a built-in command of GridView like insert, update or delete, on row command you can use the following code to get the index:
int index = Convert.ToInt32(e.CommandArgument);
In a custom command, you can set the command argument to yourRow.RowIndex.ToString() and then get it back in the RowCommand event handler. Unless, of course, you need the command argument for another purpose.
I was able to use #rahularyansharma's answer above in my own project, with one minor modification. I needed to get the value of particular cells on the row on which the user clicks a LinkButton. The second line can be modified to get the value of as many cells as you wish.
Here is my solution:
GridViewRow gvr = (GridViewRow)(((LinkButton)e.CommandSource).NamingContainer);
string typecore = gvr.Cells[3].Text.ToString().Trim();
protected void gvProductsList_RowCommand(object sender, GridViewCommandEventArgs e)
{
try
{
if (e.CommandName == "Delete")
{
GridViewRow gvr = (GridViewRow)(((ImageButton)e.CommandSource).NamingContainer);
int RemoveAt = gvr.RowIndex;
DataTable dt = new DataTable();
dt = (DataTable)ViewState["Products"];
dt.Rows.RemoveAt(RemoveAt);
dt.AcceptChanges();
ViewState["Products"] = dt;
}
}
catch (Exception ex)
{
throw;
}
}
protected void gvProductsList_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
try
{
gvProductsList.DataSource = ViewState["Products"];
gvProductsList.DataBind();
}
catch (Exception ex)
{
}
}

Deleting a row in datagrid view

I want to Delete a row in the Gridview which is in the update panel . But instead of the command button ., i took a link button to get a confirmation message. Now if I press ok then the record should be deleted (both from db and frm girdview). I know how to delete from db but not when linkbutton is pressed, and deleting the record. And also the gridview is in update panel.so it should be reflected.
A sample code is appreciated.
Thanks
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
GridViewRow row = (GridViewRow)(((LinkButton)e.CommandSource).NamingContainer);
String productId = row.Cells[0].Text; // I suposed your product Id in very first column in gridview
//Delete Code goes here..........
...........................
}
}
you can use RowCommand event of gridview, like...
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
e.CommandArgument -- this return Data Key Value
//Deletion Code goes here.....
var brochureToDelete = (from b in dataContext.ArticleBrochures where b.ArticleId == ArticleId select b).FirstOrDefault();
if (brochureToDelete != null)
{
dataContext.ArticleBrochures.DeleteOnSubmit(brochureToDelete);
dataContext.SubmitChanges();
bindBrochureGridView(ArticleId);
// if your gridview in updatepanel
//Call update method of UpdatePanel
//UpdatePanel.Update();
}
}
Set PK_ID to link button's command args like that
<asp:LinkButton runat="server" ID="btn_manage" Text="Delete" CommandArgument='<%#Eval("PK_ID") %>'
OnCommand="btn_manage_click">
</asp:LinkButton>
and access this PK_ID on event
protected void btn_manage_click(object sender, CommandEventArgs e)
{
string ID = e.CommandArgument.ToString();
//you delete code and gridview bind code
}
bind the linkbutton id as the primary key. On client clicking the link button save that id in a hidden field. This hidden field value will be the id of row to be deleted.
Then on the server click of link button delete the row corresponding to the hidden field value
I presume you have a method which sends a delete query.
Make a RowDeleting event handler, pass your row index using e.RowIndex to the delete method.
Use this e.RowIndex to write a query to delete the 'n'th row of your table. and then bind the data to your gridView.

Gridview - Reference to a new column

I have a gridview which takes in data from 3 tables.
And this gridview also have an additional column called "Role" which is not included in the database.
Currently, without adding any logic but simply using the findcontrol to the label, "Role", i can show out "ML"
But, when I add in the logic, it did not appear at all.
In any case, does anyone knows how to insert "ML" into the "Role" column which is not found in the database but is reference from another column found in the database.
This is the codes used to display the "ML" in the role column.
protected void gridAMDisplay_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//find the Label control using FindControl and set its Text on some column value
DataRowView row = (DataRowView)e.Row.DataItem;
if (!DBNull.Value.Equals(row["ModuleLeader"]))
{
if (row["ModuleLeader"].ToString() == "ModuleStr")
{
Label lbl = e.Row.FindControl("lblRole") as Label;
if (lbl != null)
{
lbl.Text = "ML";
}
}
}
}
}
This part of the code when comment off, the ML can be displayed in the role column, otherwise, nothing is displayed.
Therefore, i feel that the findcontrol part works. BUT, referencing does not works.
if (row["ModuleLeader"].ToString() == "ModuleStr")
{
As i mentioned, the role column was not included in any of the tables in the DB.
Therefore, i added in this codes.
<asp:TemplateField HeaderText="Role">
<ItemTemplate>
<asp:Label ID="lblRole" runat="server" Text="" />
</ItemTemplate>
</asp:TemplateField>
But, the problem i have now is, the role column does not reference to the column it is supposed to, which is "Module Leaders"
You reference the DataItem, which cannot be used in DataBound, you should use OnDataBinding to implement this.
It seems you only want the role column to update to "ML" based on the data present in another column of the same row. Why not just drop it in the XHTML?
<asp:TemplateField HeaderText="Role">
<ItemTemplate>
<asp:Label ID="lblRole" runat="server" Text='<%# GetRoleString(Eval("ModuleLeader"))%>' />
</ItemTemplate>
</asp:TemplateField>
Then in the code behind you could have a method:
string GetRoleString(string moduleLeader)
{
return (moduleLeader == "ModuleStr") ? "ML" : "";
}
This would occur on databinding and would only happen once per row.
The best practice in my humble opinion is to create your own template.
Here is one for your case :
public class NotEmptyValueFromDataTemplate : System.Web.UI.Page, IBindableTemplate
{
protected string p_DataFieldToLookAt;
protected string p_ValueToPlaceInIfNotNull;
protected Literal p_litControl;
public RoleTemplate(string DataFieldToLookAt, string ValueToPlaceInIfNotNull)
{
this.p_DataFieldToLookAt = DataFieldToLookAt;
this.p_ValueToPlaceInIfNotNull = ValueToPlaceInIfNotNull;
}
public virtual void OnInit(object sender, EventArgs e)
{ }
#region IBindableTemplate Members
public System.Collections.Specialized.IOrderedDictionary ExtractValues(Control container)
{
throw new NotImplementedException();
}
#endregion
#region ITemplate Members
public void InstantiateIn(Control container)
{
p_litControl = new Literal();
p_litControl.ID = p_DataFieldToLookAt; /* we don't really care */
p_litControl.Init += new EventHandler(OnInit);
p_litControl.DataBinding += new EventHandler(p_litControl_DataBinding);
container.Controls.Add(p_litControl);
}
void p_litControl_DataBinding(object sender, EventArgs e)
{
var Data = ((GridViewRow)(p_litControl.NamingContainer)).DataItem;
string ValueFromData = Convert.ToString(DataBinder.Eval(Data, p_DataFieldToLookAt));
if(!String.IsNullOrEmpty(ValueFromData))
p_litControl.Text = p_ValueToPlaceInIfNotNull;
}
protected override void OnDataBinding(EventArgs e)
{
base.OnDataBinding(e);
}
#endregion
}
You have then to instantiate each template row :
protected void GridView3_Init(object sender, EventArgs e)
{
((TemplateField)(GridView3.Columns[/* Column Index Here*/])).ItemTemplate = new NotEmptyValueFromDataTemplate("ModuleLeader", "ML");
}
Last, create the template item in the gridview :
<asp:TemplateField HeaderText="Role"></asp:TemplateField>
PS : Code is untested and written out of solution

Categories

Resources