How To DataBind Button per row in a gridview [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Hi I was wondering how would I be able to get the particular cell value in my gridview (assuming that it only returns 1 row) so I would be able to overwrite other data in the db that is associated to that cell value. I'm thinking of data binding button per row, but how would I be able to do that?
here is my markup for gridview:
<asp:GridView id="gvInfo" runat="server" OnRowCommand="Convert.ToInt32(e.CommandArgument);" AutoGenerateColumns="true" EmptyDataText="Sorry, No Results Found. Enter User again." Visible="true">
<Columns>
<asp:TemplateField HeaderText="Test" >
<ItemTemplate>
<asp:Button id="btnUpdate" Text="Update" runat="server" OnClick="update" Visible="false"/>
<asp:Button id="btnUpdatePin" Text="Update Pin" runat="server" OnClick="updatePin" Visible="false" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I have tried this to get it but nothing happened:
protected void update(object sender, EventArgs e)
{
int status;
string idc = gvInfo.SelectedRow.Cells[0].Text;
if (chkIsAuthorized.Checked == true)
{
status = 1;
}
else
{
status = 0;
}
string sql="UPDATE starlode_users SET isauthorized = #isauthorized WHERE idcnumber=#idcnumber;";
string cs = ConfigurationManager.ConnectionStrings ["DBCON"].ConnectionString;
using (NpgsqlConnection dbcon = new NpgsqlConnection(cs))
{
dbcon.Open();
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, dbcon))
{
cmd.Parameters.AddWithValue("#isauthoried", status);
cmd.Parameters.AddWithValue("#idcnumber", idc);
cmd.ExecuteNonQuery();
}
}
}
Would appreciate any help. Thanks.

Add CommandArgument='<%# Container.DataItemIndex %>' to your button and in your code behind you can get the row that raised the event.
<asp:Button ID="btnUpdate" runat="server" Text="Update" CommandName="UpdateData" CommandArgument='<%# Container.DataItemIndex %>'/>
In your codebehind subscribe to gridview's row command event.
protected void gvInfo_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "UpdateData")
{
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow row = gvInfo.Rows[index];
string cellText = row.Cells[0].Text;
}
}

You can get GridViewRow of SelectedRow upon Button click by type casting the sender parameter to get the reference of the GridViewRow
protected void update(object sender, EventArgs e)
{
Button btn = sender as Button;
GridViewRow gr = (btn.NamingContainer as GridViewRow);
string idc = gr.Cells[0].Text;
}

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!

how to get value of a template field label of a gridview, getting error Object reference not set to an instance of an object

While getting the value I'm getting Object reference not set to an instance of an object. how to get labeled label value in code behind. How to get the value in custom event
<asp:GridView runat="server" ID="gridviewQuoteDetails" EmptyDataText="No records Found..." AutoGenerateEditButton="false" OnRowEditing="gridviewQuoteDetails_RowEditing" OnRowUpdating="gridviewQuoteDetails_RowUpdating" DataKeyNames="id" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<a href='Quote.aspx?val=<%#Eval("id")%>'>
<asp:Label ID="lblid" runat="server" Text='<%#Eval ("id")%>'></asp:Label>
</a>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" Text="Edit" runat="server" CommandName="Edit" />
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="LinkButton2" Text="Update" runat="server" OnClick="OnUpdate" />
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
code behind
protected void OnUpdate(object sender, EventArgs e)
{
string qouteid = ((Label)gridviewQuoteDetails.FindControl("lblid")).Text;
GridViewRow row = (sender as LinkButton).NamingContainer as GridViewRow;
string id = (row.Cells[0].Controls[0] as TextBox).Text;
string Description = (row.Cells[1].Controls[0] as TextBox).Text;
}
Gridview is a collection of rows right, but you are trying to search the control directly within the gridview thus ((LinkButton)gridviewQuoteDetails.FindControl("lbllnknm")) will be null and when you are trying to access the Text property of LinkButton you are getting NRE error.
You need to loop through the rows of your gridview control to access each linkbutton present in each row like this:-
foreach (GridViewRow row in gridviewQuoteDetails.Rows)
{
LinkButton lbllnknm= row.FindControl("lbllnknm") as LinkButton;
}
But ideally you would not be needing this. I guess you are trying to get the value in OnRowEditing event handler. If that is the case then you can fetch the value of linkbutton like this:-
protected void gridviewQuoteDetails_RowEditing(object sender, GridViewUpdateEventArgs e)
{
string qouteid = ((Label)gridviewQuoteDetails.Rows[e.NewEditIndex]
.FindControl("lbllnknm")).Text;
}
Update 2:
As per your comment you are trying to access the LinkButton text on click of LinkButton itself which means the event is raised by LinkButton itself. You can simply use the sender object like this:-
protected void OnUpdate(object sender, EventArgs e)
{
LinkButton LinkButton2 = sender as LinkButton;
GridViewRow row = LinkButton2.NamingContainer as GridViewRow; //Get the gridview row
Label lblid = row.FindControl("lblid") as Label;
string qouteid = lblid.Text;
}

Dynamically added controls missing during GridView RowUpdating

I have a GridView with a TemplateField column that I put PlaceHolder controls in. During the DataBound event for the GridView I dynamically add a few CheckBoxes to the PlaceHolder. That works fine and displays as expected.
My problem is that during the RowUpdating event the PlaceHolder contains no controls; my CheckBoxes are missing. I also noticed that they're missing during the RowEditing event.
I want to be able to get the values of the CheckBoxes during the RowUpdating event so I can save them to the database.
Here's some example code. I've trimmed out a lot to reduce size, but if you want to see specifics just ask and I'll be happy to add more.
HTML:
<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False"
ondatabound="gridView_DataBound" onrowupdating="gridView_RowUpdating"
onrowediting="gridView_RowEditing" DataKeyNames="ID">
<Columns>
<asp:TemplateField HeaderText="Countries">
<ItemTemplate>
<asp:PlaceHolder ID="countriesPlaceHolder" runat="server"></asp:PlaceHolder>
</ItemTemplate>
<EditItemTemplate>
<asp:PlaceHolder ID="countriesPlaceHolder" runat="server"></asp:PlaceHolder>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="editButton" runat="server" CommandName="Edit" Text="Edit"></asp:LinkButton>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="updateButton" runat="server" CommandName="Update" Text="Update"></asp:LinkButton>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code behind:
// This method works fine, no obvious problems here.
protected void gridView_DataBound(object sender, EventArgs e)
{
// Loop through the Holidays that are bound to the GridView
var holidays = (IEnumerable<Holiday>)gridView.DataSource;
for (int i = 0; i < holidays.Count(); i++)
{
// Get the row the Holiday is bound to
GridViewRow row = gridView.Rows[i];
// Get the PlaceHolder control
var placeHolder = (PlaceHolder)row.FindControl("countriesPlaceHolder");
// Create a CheckBox for each country and add it to the PlaceHolder
foreach (Country country in this.Countries)
{
bool isChecked = holidays.ElementAt(i).Countries.Any(item => item.ID == country.ID);
var countryCheckBox = new CheckBox
{
Checked = isChecked,
ID = country.Abbreviation + "CheckBox",
Text = country.Abbreviation
};
placeHolder.Controls.Add(countryCheckBox);
}
}
}
protected void gridView_RowEditing(object sender, GridViewEditEventArgs e)
{
// EXAMPLE: I'm expecting checkBoxControls to contain my CheckBoxes, but it's empty.
var checkBoxControls = gridView.Rows[e.NewEditIndex].FindControl("countriesPlaceHolder").Controls;
gridView.EditIndex = e.NewEditIndex;
BindData();
}
protected void gridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
// EXAMPLE: I'm expecting checkBoxControls to contain my CheckBoxes, but it's empty.
var checkBoxControls = ((PlaceHolder)gridView.Rows[e.RowIndex].FindControl("countriesPlaceHolder")).Controls;
// This is where I'd grab the values from the controls, create an entity, and save the entity to the database.
gridView.EditIndex = -1;
BindData();
}
This is the article that I followed for my data binding approach: http://www.aarongoldenthal.com/post/2009/04/19/Manually-Databinding-a-GridView.aspx
You need to call your BindData() method on page load.
"Dynamic controls or columns need to be recreated on every page load, because of the way that controls work. Dynamic controls do not get retained so you have to reload them on every page postback; however, viewstate will be retained for these controls."
See Cells in gridview lose controls on RowUpdating event
Also in the article you linked, there is an ItemTemplate and an EditItemTemplace because they have different displays, i.e. read only and editable. Yours are the same so I think you could simplify your design:
<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" ondatabound="gridView_DataBound">
<Columns>
<asp:TemplateField HeaderText="Countries">
<ItemTemplate>
<asp:PlaceHolder ID="countriesPlaceHolder" runat="server"></asp:PlaceHolder>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="editButton" runat="server" Text="Edit" onclick="editButton_Click" ></asp:LinkButton>
<asp:LinkButton ID="updateButton" runat="server" Text="Update" onclick="updateButton_Click" ></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code Behind:
protected void gridView_DataBound(object sender, EventArgs e)
{
// Loop through the Holidays that are bound to the GridView
var holidays = (IEnumerable<Holiday>)gridView.DataSource;
for (int i = 0; i < holidays.Count(); i++)
{
// Get the row the Holiday is bound to
GridViewRow row = gridView.Rows[i];
// Get the PlaceHolder control
var placeHolder = (PlaceHolder) row.FindControl("countriesPlaceHolder");
var countryCheckBox = new CheckBox
{
Checked = true,
ID = "auCheckBox",
Text = "Aus",
Enabled = false
};
placeHolder.Controls.Add(countryCheckBox);
var editButton = (LinkButton)row.FindControl("editButton");
editButton.CommandArgument = i.ToString();
var updateButton = (LinkButton)row.FindControl("updateButton");
updateButton.CommandArgument = i.ToString();
updateButton.Visible = false;
}
}
protected void editButton_Click(object sender, EventArgs e)
{
LinkButton editButton = (LinkButton) sender;
int index = Convert.ToInt32(editButton.CommandArgument);
GridViewRow row = gridView.Rows[index];
// Get the PlaceHolder control
LinkButton updateButton = (LinkButton)row.FindControl("updateButton");
updateButton.Visible = true;
editButton.Visible = false;
CheckBox checkbox = (CheckBox)row.FindControl("auCheckBox");
if (checkbox != null)
{
checkbox.Enabled = true;
// Get value and update
}
}
protected void updateButton_Click(object sender, EventArgs e)
{
LinkButton updateButton = (LinkButton)sender;
int index = Convert.ToInt32(updateButton.CommandArgument);
GridViewRow row = gridView.Rows[index];
// Get the PlaceHolder control
LinkButton editButton = (LinkButton)row.FindControl("updateButton");
editButton.Visible = true;
updateButton.Visible = false;
CheckBox checkbox = (CheckBox)row.FindControl("auCheckBox");
if (checkbox != null)
{
// Get value and update
checkbox.Enabled = false;
}
}
If you want to be it enabled from the get go, just remove the enabled checks and you can delete your edit button.
Hope that helps.

Adding functionality to an imageButton in a gridview

I have an ImageButton control as part of a GridView control that is displayed as an ItemTemplate and in the same GridView. I have a regular Button control to which I added some code like this
if (e.CommandName == "addToSession")
{
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow selectedRow = ((GridView)e.CommandSource).Rows[index];
string ISBN = selectedRow.Cells[0].Text;
string bookTitle = selectedRow.Cells[1].Text;
string image = selectedRow.Cells[2].Text;
//storing title, author, pictureUrl into session variables to 'carry them over' to RateBook.aspx
Service s = new Service();
Session["ISBN"] = ISBN;
Session["bookTitle"] = bookTitle;
Session["ImageUrl"] = s.returnImageUrl(bookTitle);
if (Session["userName"] == null)
{
Response.Redirect("registerPage.aspx");
}
else
{
Response.Redirect("RateBook.aspx");
}
}
else if (e.CommandName == "ratedBooks")
{
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow selectedRow = ((GridView)e.CommandSource).Rows[index];
string bookTitle = selectedRow.Cells[1].Text;
Service s = new Service();
Session["ImageUrl"] = s.returnImageUrl(bookTitle);
Response.Redirect("BookRated.aspx");
}
when I run this code I get a format exception and again I am not sure why. I have altered the image button a bit and nested the image in a link button which seems to be more correct.
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CommandName="ratedBooks">
<asp:Image ID="ImageButton1" ImageUrl='<%#Eval("pictureUrl") %>' runat="server" />
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
Please advise.
Regards,
Arian
I believe you can accomplish your needs with an ImageButton, as it supports all the major Button functionality, including CommandName (see http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.imagebutton.commandname.aspx).
Try this out:
<asp:ImageButton ID="LinkButton1" runat="server"
CommandName="ratedBooks"
ImageUrl='<%#Eval("pictureUrl") %>' />
Also, note that your format exception could be coming from the lines that read:
Convert.ToInt32(e.CommandArgument);
The reason being that there appears from this code snippet to be no value assigned to the CommandArgument of the button. Convert.ToInt32 requires a valid integer value to be passed in, which means that the ImageButton needs to have a number bound to its CommandArgument property.
If you based your solution on this MSDN reference (http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridviewcommandeventargs.aspx), note that the <asp:ButtonField> column type gets special treatment; the CommandArgument is set to the row index. When you use a template field, ASP.NET requires you to specify or data bind your own command argument.
Update
This question contains details on binding the grid view row index to a custom button:
ASP.NET GridView RowIndex As CommandArgument
A possible solution is to add the ItemDataBound event handler and search for the image button change its image url.
MyGrid.RowDataBound += new RepeaterItemEventHandler(MyGrid_RowDataBound);
void MyGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowIndex > -1)
{
ImageButton image = e.Row.FindControl("MY_IMAGE_CONTROL") as ImageButton;
image.ImageUrl = "PATH_TO_IMAGE";
}
}
Hope it helps.
You need CommandArgument
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:ImageButton ID="ImageButton1" runat="server" CommandName="Delete" CommandArgument="<%# ((GridViewRow) Container).RowIndex %>" ImageUrl="~/Modelos/Img/deleted.gif" />
</ItemTemplate>
</asp:TemplateField>
code behind C#
public void GridView_RowCommand(Object sender, GridViewCommandEventArgs e)
{
string t;
if (e.CommandName == "Delete")
{
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow selectedRow = grid1.Rows[index];
t = selectedRow.Cells[2].Text;
}
}
On ASPX
<asp:GridView ID="grid1" runat="server" onselectedindexchanged="GridView1_SelectedIndexChanged" ...

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