I am trying to delete multiple grid view records. I tried as shown below.
public void btnDelete_Click(object sender, EventArgs e)
{
StringCollection orderNumberCollection = new StringCollection();
if (gridOrders.Rows.Count > 0)
{
foreach (GridViewRow gvrow in gridOrders.Rows)
{
if (gvrow.RowType == DataControlRowType.DataRow) {
CheckBox cbx = (CheckBox)gvrow.Cells[0].FindControl("chkdelete");
Label lblOrderNumner = (Label)gvrow.FindControl("labelOrderNumber");
Label lastName = (Label)gvrow.FindControl("LabelLastName");
if (cbx.Checked && lblOrderNumner != null)
{
orderNumberCollection.Add(lblOrderNumner.Text);
}
}
}
}
if (orderNumberCollection.Count > 0)
{
DeleteMultipleOrders(orderNumberCollection);
}
}
But always check box control showing "Checked = false". Why check box control always showing false even I checked some of the check boxes?
Here is my Grid view code:
<asp:TemplateField>
<HeaderTemplate>
<table><tr><td ><asp:CheckBox ID="chkAll" runat="server" /></td><td><asp:Button ID="btnDelete" runat="server" Text="Delete" OnClick="btnDelete_Click" /></td></tr></table>
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkdelete" runat="server" Text='<%# Bind("OrderNumber") %>' Font-Bold="false" />
</ItemTemplate>
</asp:TemplateField>
I'm with Tim on this, it sounds like you are loading your gridview from within Page_Load, which is fine. but in your case you would need to make sure your gridview loading code looks like this:
if(!Page.IsPostBack)
{
//gridview loading code
}
this prevents your gridview from being reloaded (and losing which boxes are checked) when you click your delete button
Related
I have a couple of GridViews in my FormView page and I am wanting to make an Insert row in the FooterRow of the Gridviews. Layout and everything is fine. However, as I'm building the codebehind for the Insert command, I'm running into a context problem. If I move the GridView outside of the FormView markup, the context errors clear up immediately.
GridView Markup
<asp:GridView ID="gvBFMats" runat="server" ShowFooter="True" AutoGenerateColumns="False" DataKeyNames="MaterialID" DataSourceID="BFMatsSQL" OnRowCommand="gvBFMats_RowCommand">
<Columns>
<asp:TemplateField HeaderText="Commands" ShowHeader="False">
<EditItemTemplate>
<asp:LinkButton ID="ButtonUpdate" runat="server" CausesValidation="True" CommandName="Update" Text="Update"></asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel"></asp:LinkButton>
</EditItemTemplate>
<ItemTemplate>
<asp:LinkButton ID="ButtonEdit" runat="server" CausesValidation="False" CommandName="Edit" Text="Edit"></asp:LinkButton>
<asp:LinkButton ID="ButtonDelete" runat="server" CausesValidation="False" CommandName="Delete" Text="Delete"></asp:LinkButton>
</ItemTemplate>
<FooterTemplate>
<asp:LinkButton ID="ButtonAdd" runat="server" CommandName="Insert" Text="Add to Table" />
</FooterTemplate>
...
Insert Command Codebehind
protected void gvBFMats_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Insert" && Page.IsValid)
{
BFMatsSQL.Insert();
}
}
protected void BFMatsSQL_Inserting
(object sender, ObjectDataSourceMethodEventArgs e)
{
DropDownList ddlNewMfr =
(DropDownList)gvBFMats.FooterRow.FindControl("ddlNewMfr");
DropDownList ddlNewThickness =
(DropDownList)gvBFMats.FooterRow.FindControl("ddlNewThickness");
DropDownList ddlNewCore =
(DropDownList)gvBFMats.FooterRow.FindControl("ddlNewCore");
DropDownList ddlNewSize =
(DropDownList)gvBFMats.FooterRow.FindControl("ddlNewSize");
TextBox txtNewColor =
(TextBox)gvBFMats.FooterRow.FindControl("txtNewColor");
TextBox txtNewQty =
(TextBox)gvBFMats.FooterRow.FindControl("txtNewQty");
DropDownList ddlNewFinish =
(DropDownList)gvBFMats.FooterRow.FindControl("ddlNewFinish");
TextBox txtNewExtra =
(TextBox)gvBFMats.FooterRow.FindControl("txtNewExtra");
// Set the SQLDataSource's InsertParameters values
e.InputParameters["MatManufacturerID"] =
Convert.ToInt32(ddlNewMfr.SelectedValue);
e.InputParameters["MatThicknessID"] =
Convert.ToInt32(ddlNewThickness.SelectedValue);
e.InputParameters["MatCoreID"] =
Convert.ToInt32(ddlNewCore.SelectedValue);
e.InputParameters["MatSizeID"] =
Convert.ToInt32(ddlNewSize.SelectedValue);
e.InputParameters["MatFinishPrePostID"] =
Convert.ToInt32(ddlNewFinish.SelectedValue);
string strNewColor = null;
if (!string.IsNullOrEmpty(txtNewColor.Text))
strNewColor = txtNewColor.Text;
e.InputParameters["MatFinishColor"] = strNewColor;
int? intNewQty = null;
if (!string.IsNullOrEmpty(txtNewQty.Text))
intNewQty = Convert.ToInt32(txtNewQty.Text);
e.InputParameters["MatQty"] = intNewQty;
string strNewExtra = null;
if (!string.IsNullOrEmpty(txtNewExtra.Text))
strNewExtra = txtNewExtra.Text;
e.InputParameters["MatNumExtraSheets"] = strNewExtra;
}
Specifically, I get the red squiggly under the gvBFMats in the (Control)gvBFMats.FooterRow.FindControl("Control ID"); that says "The name 'gvBFMats' does not exist in the current context." I'm only guessing that it doesn't like the call to the GridView when it's nested inside a FormView template. Is there a way to pass this context along programatically?
You're right about it not recognizing the name gvBFMats because it's embedded in a template. Only "top-level", non-embedded controls will be treated in Code Behind as if they had been explicitly declared. Controls declared in a template will not. The compiler doesn't recognize those names.
There's a reason for this. Imagine you have a control called TextBox1 in one of the ItemTemplates for a repeating control. You bind it. Your page's control tree now has dozens of controls with the ID TextBox1. If you want to refer to TextBox1, how does it know which one you mean?
So. What can you do in your situation? Well, BFMatsSQL_Inserting and gvBFMats_RowCommand are both event handlers, so you can't change their signatures.
But, you can make use of them belonging to the same class, and use a module-level variable to hold the reference to gvBFMats. Like this:
private GridView gvBFMats;
protected void gvBFMats_RowCommand(object sender, GridViewCommandEventArgs e)
{
gvBFMats = [your form view].Row.FindControl("gvBFMats") as GridView;
if (e.CommandName == "Insert" && Page.IsValid)
{
BFMatsSQL.Insert();
}
}
Now, BFMatsSQL_Inserting will be able to refer to gvBFMats, and it should have a value.
Not sure what is causing this I have tried a few suggestions none seem to help. I have debugged my application dozens of times and the problem never occur while debugging everything steps through just fine. But when I publish my application and allow people to use it is when the problem occurs and it is not for everyone just randomly decides that a checkbox is not checked and skips the whole process also on the front end I have a validation that requires at least one checkbox to checked before the button_click will fire so I know that they had to have one checked.
Gridview
<div id="divEventDetail">
<asp:GridView ID="grdEventDetail" runat="server" AutoGenerateColumns="False" DataKeyNames="EDID" Width="381px" OnRowDataBound="grdEventDetail_RowDataBound" GridLines="Horizontal">
<Columns>
<asp:TemplateField HeaderText="EventID" Visible="False">
<ItemTemplate>
<asp:Label ID="lblEventID" runat="server" Text='<%# Eval("EDID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Register" ItemStyle-CssClass="template-center">
<ItemTemplate >
<asp:CheckBox ID="chkRegister" runat="server"/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Wait List" ItemStyle-CssClass="template-center">
<ItemTemplate>
<asp:CheckBox ID="chkWaitList" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
CodeBehind
protected void registerEvent()
{
foreach (GridViewRow row in grdEventDetail.Rows)
{
CheckBox chkR = row.FindControl("chkRegister") as CheckBox;
CheckBox chkW = row.FindControl("chkWaitList") as CheckBox;
if (chkR != null && chkW != null)// It is a datarow
{
GridViewRow Rowr = ((GridViewRow)chkR.Parent.Parent);
GridViewRow Roww = ((GridViewRow)chkW.Parent.Parent);
if ((chkR.Checked) || (chkW.Checked))
// if ((((CheckBox)row.FindControl("chkRegister")).Checked == true) || (((CheckBox)row.FindControl("chkWaitList")).Checked == true))
{
Label eventID = row.FindControl("lblEventID") as Label;
***Then i do my database stuff here
I believe the grdEventDetail GridView doesn't have CheckBoxes in each row. For example, HeaderRow and FooterRow probably don't have those CheckBoxes.
I would rewrite the code to eliminate any error:
protected void registerEvent()
{
foreach (GridViewRow row in grdEventDetail.Rows)
{
CheckBox chkR = row.FindControl("chkRegister") as CheckBox;
CheckBox chkW = row.FindControl("chkWaitList") as CheckBox;
if(chkR != null && chkW != null)// It is a datarow
{
GridViewRow Rowr = ((GridViewRow)chkR.Parent.Parent);
GridViewRow Roww = ((GridViewRow)chkW.Parent.Parent);
if ((chkR.Checked) || (chkW.Checked))
{
//Your code goes here
}
}
}
}
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.
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.
I have a GridView :
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" GridLines="None"
HorizontalAlign="Left" AutoGenerateColumns="False"
DataSourceID="SqlDataSource1" onrowcommand="GridView1_RowCommand1">
<HeaderStyle HorizontalAlign="Left" />
<Columns>
<asp:TemplateField HeaderStyle-Width="150">
<HeaderTemplate>
<b>Downloads</b>
</HeaderTemplate>
<ItemTemplate>
<!-- <asp:HyperLink ID="hyperlinkDownload" runat="server" NavigateUrl="" >Download
MP3</asp:HyperLink> -->
<asp:LinkButton CommandName="download"
CommandArgument='<%# Eval("Name") %>' runat="server">Download MP3</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</asp:GridView>
I want to query the value of a particular field in a DB and if it's true, display the LinkButton. if false, I want the linkButton not to be displayed.
is there a way to access the GridView programmatically and make visible certain of its columns or manipulate its items ?
help.
You can do this by adding a handler to the RowDataBound event. Add an event handler along this lines of this in your code behind:
protected void myGrid_RowDataBound(Object sender, GridViewRowEventArgs e)
{
var data = e.Row.DataItem as DataRowView;
if (data != null)
{
var lbtDownload = e.Row.FindControl("lbtDownload");
lbtDownload.Visible = (bool) data.Row["HasFileForDownload"];
}
}
In your markup, attach the event handler to the grid:
<asp:GridView OnRowDataBound="myGrid_RowDataBound" ...>
You will also need to assign an id to the LinkButton, matching the one that you are search for using the FindControl() method in the event handler.
Disclaimer: I am on currently a Linux machine with no chance of testing this. Please report any bugs in the code - feel free to correct them if you have editor rights.
Yes there is.
1) You need to subscribe the RowDataBound event.
2) Give the LinkButton an ID.
3) Insert in codebehind
protected void GridView1_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
LinkButton _bt = e.Row.FindControl("ID") as LinkButton;
if(_bt != null)
{
// have a look at the e.row.DataItem and try to get the value of your desired visibility property
_bt.Visible = true;
}
}
}
4) If this does not work with accessing the DataItem, start thinking about a LinqDataSource.