Bulk Edit Update Multiple Rows in ASP.Net GridView using CheckBoxes - c#

you can see VT_AClReport Table design In the below HTML Markup I have a simple ASP.Net GridView with 3 columns.
First column containing the CheckBox, second column containing a Label for display ID and Access Path of the folder respectively and the third column containing a Label and DropDownList for display and edit status of the folder respectively.
Here I am using GridView with paging to display the data, and the data is about millions of rows. When I click on submit button to update the checkbox selected rows, execution time is taking too much to update the rows in table.
For Example: for 5000 rows = 26 min.
Can anyone help me to resolve this issue and reduce the execution time to update all the records within few seconds.
Please see the code:
<asp:GridView ID="gvACLReport" runat="server" AutoGenerateColumns="False"CssClass="mgrid" EmptyDataText="No Records Exists..." DataKeyNames="ACLId" ShowFooter="True" HorizontalAlign="Center" Width="100%" AllowPaging="True" EnableSortingAndPagingCallback="True" PageSize="500" AllowSorting="True" Visible="False" onpageindexchanging="gvACLReport_PageIndexChanging" EnableSortingAndPagingCallbacks="True">
<AlternatingRowStyle CssClass="mgridalt" />
<PagerSettings PageButtonCount="10000" />
<PagerStyle CssClass="gridview" HorizontalAlign="Center"></PagerStyle>
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<asp:CheckBox ID="chkAllACLReport" runat="server" AutoPostBack="true" OnCheckedChanged="OnCheckedChanged" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkACLReport" runat="server" AutoPostBack="true" OnCheckedChanged="OnCheckedChanged"/>
</ItemTemplate>
<ItemStyle Width="20px" />
</asp:TemplateField>
<asp:TemplateField HeaderText="ACL Id">
<ItemTemplate>
<asp:Label ID="lblACLId" runat="server" Text='<%# Eval("ACLId") %>'></asp:Label>
</ItemTemplate>
<ItemStyle Width="20px" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Access Path">
<ItemTemplate>
<asp:TextBox ID="lblAccessPathACL" runat="server" Rows="3" Width="400px" Text='<%# Eval("AccessPath") %>'ReadOnly="True" TextMode="MultiLine" BorderStyle="None" BorderWidth="0px" BackColor="Transparent"></asp:TextBox>
</ItemTemplate>
<ItemStyle Width="150px" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Directory Name">
<ItemTemplate>
<asp:TextBox ID="lblDirectoryName" runat="server" Rows="3" Width="400px" Text='<%# Eval("DirectoryName") %>'ReadOnly="True" TextMode="MultiLine" BorderStyle="None" BorderWidth="0px" BackColor="Transparent"></asp:TextBox>
</ItemTemplate>
<ItemStyle Width="150px" />
</asp:TemplateField>
<asp:TemplateField HeaderText="User Group">
<ItemTemplate>
<asp:Label ID="lblUserGroup" runat="server" Text='<%# Eval("UserGroup") %>'></asp:Label>
</ItemTemplate>
<ItemStyle Width="150px" />
</asp:TemplateField>
</Columns>
<HeaderStyle CssClass="mgridheader" />
<RowStyle CssClass="mgriditem" />
</asp:GridView>
//Please check this the table contain the drop down list to update the status and submit and clear button
<table id ="tableChangeStatus" align="center" width="100%"
class="body style1" cellspacing="4" style="border-color: #808080;
border-style: solid; border-width: 1px; table-layout: auto;"
runat="server" visible="False">
<tr runat="server">
<td align="left" runat="server">
Status:
</td>
<td runat="server">
<asp:DropDownList ID="ddlChangeStatus" AutoPostBack="True" AppendDataBoundItems="True"
runat="server" Width="200px" DataSourceID="SDSChangeStatus" DataTextField="Status"
DataValueField="StatusId">
<asp:ListItem Text="--Select--" Value="0"></asp:ListItem>
</asp:DropDownList>
<asp:SqlDataSource ID="SDSChangeStatus" runat="server" ConnectionString="<%$ ConnectionStrings:gtsgeneralconn %>"
SelectCommand="VT_getStatusList" SelectCommandType="StoredProcedure"></asp:SqlDataSource>
<asp:RequiredFieldValidator ID="RequiredFieldValidator4" runat="server" ControlToValidate="ddlChangeStatus"
Display="Dynamic" ErrorMessage="Select Status" InitialValue="0" SetFocusOnError="True">*</asp:RequiredFieldValidator>
</td>
</tr>
<tr runat="server">
<td align="center" colspan="2" runat="server">
<asp:Button ID="btnChangeStatus" runat="server" Text="Submit" CausesValidation="False"
onclick="btnChangeStatus_Click"
/>
<asp:Button ID="btnChangeClear" runat="server" Text="Clear"
CausesValidation="False" onclick="btnChangeClear_Click"
/>
</td>
</tr>
</table>
Code Behind:
protected void ChangeStatusGlobalSensitiveNonSensitiveReport()
{
int rowsAffected = 0;
foreach (GridViewRow row in gvGlobalSensitive.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
bool isChecked = row.Cells[0].Controls.OfType<CheckBox().FirstOrDefault().Checked;
if (isChecked)
{
using (SqlConnection con = new SqlConnection(cs))
{
cmd = new SqlCommand("VT_ACLReportChangeStatus", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandTimeout = 3600;
cmd.Parameters.AddWithValue("#ChangeStatus", ddlChangeStatus.SelectedItem.Text.ToString());
cmd.Parameters.AddWithValue("#ACLId", row.Cells[1].Controls.OfType<Label>().FirstOrDefault().Text);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
rowsAffected++;
}
}
}
lblUpdatedRowsMsg.Text = rowsAffected + " Rows updated!!";
lblUpdateMsg.Text = "Detail Saved Successfully!!";
gvGlobalSensitive.Visible = false;
tableChangeStatus.Visible = false;
divReport.Visible = false;
}
if (rowsAffected == 0)
{
lblUpdateMsg.Text = "Please select the check box to update the status!!";
lblUpdatedRowsMsg.Text = rowsAffected + " Rows updated!!";
}
}
Stored Procedure
ALTER PROCEDURE [dbo].[VT_ACLReportChangeStatus]
(
#ChangeStatus nvarchar(50)=null,
#ACLId int
)
AS
// Exec VT_ACLReportChangeStatus 'Complete',34
BEGIN
UPDATE VT_ACLReport SET Status = #ChangeStatus WHERE ACLId = #ACLId
End

Replace the UPDATE statement in your stored procedure with T-SQL given below.
I am assuming ACLId is the primary key with a clustered index and you have an index on Status column. You would be better off if you create another index on ACLId and include column Status in it since that will really speed up the lookup in UPDATE statement.
In this T-SQL, updates are happening in batches of 1000 records rather than updating the whole data set. You can play around with changing the value of 100 to something like 500 or even less to come up with the best update batch.
DECLARE #numberOfRowsUpdated INT = 1000, #maxRowsToUpdate INT = 1000;
BEGIN TRY
BEGIN TRAN
WHILE (#numberOfRowsUpdated > 0)
BEGIN
UPDATE TOP (#maxRowsToUpdate) VT_ACLReport SET Status = #ChangeStatus
WHERE ACLId = #ACLId and Status <> #ChangeStatus;
SET #numberOfRowsUpdated = ##ROWCOUNT;
END
if ##trancount > 0
COMMIT TRAN
END TRY
BEGIN CATCH
if ##trancount > 0
ROLLBACK TRAN
-- log and raise error
END CATCH

I solved this problem by maintaining View State, Preserving all checked checkbox state and storing in view state.
then concatenating all the id's in one variable.
protected void gvACLReport_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView gv = (GridView)sender;
PaginateTheData(gv);
gvACLReport.PageIndex = e.NewPageIndex;
UpdateACLReport();
}
protected void PaginateTheData(GridView gvAll)
{
List<int> list = new List<int>();
if (ViewState["SelectedRecords"] != null)
{
list = (List<int>)ViewState["SelectedRecords"];
}
foreach (GridViewRow row in gvAll.Rows)
{
CheckBox chk = (CheckBox)row.FindControl("chkReport");
var selectedKey = int.Parse(gvAll.DataKeys[row.RowIndex].Value.ToString());
if (chk.Checked)
{
if (!list.Contains(selectedKey))
{
list.Add(selectedKey);
}
}
else
{
if (list.Contains(selectedKey))
{
list.Remove(selectedKey);
}
}
}
ViewState["SelectedRecords"] = list;
}
}
protected void ChangeStatusACLReport()
{
int rowsAffected = 0;
List<int> list = ViewState["SelectedRecords"] as List<int>;
string ACLId = "";
if (list != null)
{
foreach (int id in list)
{
ACLId = ACLId + id.ToString() + ",";
rowsAffected++;
}
}
else
{
foreach (GridViewRow row in gvACLReport.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
bool isChecked = row.Cells[0].Controls.OfType<CheckBox>().FirstOrDefault().Checked;
if (isChecked)
{
ACLId = ACLId + row.Cells[1].Controls.OfType<Label>().FirstOrDefault().Text + ",";
rowsAffected++;
}
}
}
}
if (rowsAffected == 0)
{
lblUpdateMsg.Text = "Please select the check box to update the status!!";
lblUpdatedRowsMsg.Text = rowsAffected + " Rows updated!!";
}
else
{
ACLId = ACLId.ToString().Trim(',');
using (SqlConnection con = new SqlConnection(cs))
{
cmd = new SqlCommand("VT_ACLReportChangeStatus", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandTimeout = 3600;
//cmd.Parameters.AddWithValue("#ChangeStatus", ddlChangeStatus.SelectedItem.Text.ToString());
//cmd.Parameters.AddWithValue("#ACLId", ACLId);
cmd.Parameters.Add(new SqlParameter("#ACLId", SqlDbType.NVarChar,-1));
cmd.Parameters.Add(new SqlParameter("#ChangeStatus", SqlDbType.NVarChar, 50));
cmd.Parameters["#ACLId"].Value = ACLId;
cmd.Parameters["#ChangeStatus"].Value = ddlChangeStatus.SelectedItem.Text.ToString();
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
lblUpdatedRowsMsg.Text = rowsAffected + " Rows updated!!";
lblUpdateMsg.Text = "Detail Saved Successfully!!";
gvACLReport.Visible = false;
tableChangeStatus.Visible = false;
divReport.Visible = false;
// DeleteCompleteACLReport(ACLId);
}

Related

Finding the ID of a checkbox and single selection in a child gridview

I wanted to find the ID of a checkbox and only single select one of multiple checkboxes. I don't want to use radio buttons though.
Here's what I did so far to find the ID of the checkboxes :
protected void gvChild_RowDataBound(object sender, GridViewRowEventArgs e)
{
foreach (GridViewRow row in gvParent.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
GridView gvChild = (GridView)row.FindControl("gvChild");
// Then do the same method for check box column
if (gvChild != null)
{
foreach (GridViewRow rowChild in gvChild.Rows)
{
if (rowChild.RowType == DataControlRowType.DataRow)
{
CheckBox chk = (CheckBox)rowChild.FindControl("CbList");
if (chk.Checked)
{
string strScript = "uncheckOthers(" + ((CheckBox)e.Row.Cells[0].FindControl("CbList")).ClientID + ");";
((CheckBox)e.Row.Cells[0].FindControl("CbList")).Attributes.Add("onclick", strScript);
testLabel.Text = strScript;
}
}
}
}
}
}
}
I use "uncheckOthers()" as my javascript function to single select one and only checkbox.
NOTE : This function works properly in a parent gridview.
Here's the code to that function :
function uncheckOthers(id) {
var elm = document.getElementsByTagName('input');
for (var i = 0; i < elm.length; i++) {
if (elm.item(i).id.substring(id.id.lastIndexOf('_')) == id.id.substring(id.id.lastIndexOf('_'))) {
if (elm.item(i).type == "checkbox" && elm.item(i) != id)
elm.item(i).checked = false;
}
}
}
Last , but not least the Markup (removed boundfields for security purposes):
<asp:GridView ID="gvParent" runat="server" AutoGenerateColumns="false" CssClass="list" OnRowDataBound="OnRowDataBound" OnSelectedIndexChanged="gvParent_SelectedIndexChanged" DataKeyNames="MoodleTemplateID">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<img alt="" src="Images/view16x16.png"/>
<asp:Panel ID="pnlChild" runat="server" Style="display: none">
<asp:GridView ID="gvChild" runat="server" AutoGenerateColumns="false" CssClass = "list" DataKeyNames="ID" OnSelectedIndexChanged="gvChild_SelectedIndexChanged" OnRowDataBound="gvChild_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemStyle HorizontalAlign="Center" />
<ItemTemplate>
<asp:CheckBox ID="CbList" runat="server"/>
</ItemTemplate>
<HeaderStyle Width="20px" />
</asp:TemplateField>
<asp:CommandField ButtonType="Image" SelectImageUrl="Images/edit16x16.png" ShowSelectButton="True" SelectText="Editar">
<ItemStyle Width="10px" />
</asp:CommandField>
</Columns>
</asp:GridView>
</asp:Panel>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ButtonType="Button" ShowSelectButton="True" SelectText="Editar">
<ItemStyle Width="10px" />
</asp:CommandField>
</Columns>
</asp:GridView>
Ok, first up, I am going to suggest that the main grid is a list view.
The reason is listview supports "span" a lot better. When I try to nest gv's, they tend to look like this:
But, nesting the gridview inside of a listview, then it works much better like this:
And really amazing, is that without extra code the expanded parts persist - without really any extra code.
So here is our markup - and I added a check box to the child gv in above.
<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" >
<ItemTemplate>
<tr style="">
<td><asp:Button ID="cmdView" runat="server" Text="+" OnClick="cmdView_Click" /></td>
<td><asp:Label ID="HotelNameLabel" runat="server" Text='<%# Eval("HotelName") %>' /></td>
<td><asp:Label ID="CityLabel" runat="server" Text='<%# Eval("City") %>' /></td>
<td><asp:Label ID="ProvinceLabel" runat="server" Text='<%# Eval("Province") %>' /></td>
<td><asp:Label ID="DescriptionLabel" runat="server" Text='<%# Eval("Description") %>' /></td>
</tr>
<tr>
<td colspan="5">
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table table-hover" style="display:none" >
<Columns>
<asp:BoundField DataField="Firstname" HeaderText="Firstname" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:TemplateField HeaderText="Select">
<ItemTemplate>
<asp:CheckBox id="ckSel" runat="server"
OnCheckedChanged="ckSel_CheckedChanged"
AutoPostBack="true" >
</asp:CheckBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table id="itemPlaceholderContainer" runat="server" Class = "table table-hover" >
<tr runat="server" style="">
<th runat="server">View</th>
<th runat="server">HotelName</th>
<th runat="server">City</th>
<th runat="server">Province</th>
<th runat="server">Description</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</LayoutTemplate>
</asp:ListView>
Ok, so here is our load up the grid (well, I used listview).
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
public void LoadGrid()
{
string strSQL = #"SELECT * FROM tblHotels WHERE ID in (select hotel_Id from People)
ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL,
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
ListView1.DataSource = cmdSQL.ExecuteReader();
ListView1.DataBind();
}
}
Ok, so run the above, and we get this:
Ok, now next bus stop is the + key. This is just a plane jane regular asp.net button. And I DID NOT bother with gridview or the listview built in events (selected index and all that jazzz - its too confusing and better yet we just don't care nor need to bother with the events of those gv, or lv's.
Ok, so our code is this:
not too much!!!
protected void cmdView_Click(object sender, EventArgs e)
{
Button cmd = (Button)sender;
ListViewDataItem gVR = (ListViewDataItem)cmd.Parent;
GridView gChild = (GridView)gVR.FindControl("GridView2"); // pluck out the grid for this row
if (gChild.Style["display"] == "normal")
{
// if grid is already display, then hide it, and exit
gChild.Style["display"] = "none";
return;
}
gChild.Style["display"] = "normal";
string HotelPK = (string)ListView1.DataKeys[gVR.DataItemIndex]["ID"];
// only re-load if never loaded (can't re-load else blow out check boxes
if (gChild.Rows.Count == 0)
{
string strSQL = #"SELECT * from People where hotel_id = " + HotelPK;
using (SqlCommand cmdSQL = new SqlCommand(strSQL,
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
gChild.DataSource = cmdSQL.ExecuteReader();
gChild.DataBind();
}
}
}
Ok, so that will expand, colipase each row. and REALLY amazing is that state management works (it remembers the expand or collapse - and it WILL even remember the setting of the un-bound check box.
So, we expand say the first row. We get this:
Ok, so now the only part left is the checkbox click event. and again, not too much code:
protected void ckSel_CheckedChanged(object sender, EventArgs e)
{
CheckBox ckBox = (CheckBox)sender;
GridView gvChild = (GridView)ckBox.Parent.Parent.Parent.Parent;
GridViewRow gvRowClick = (GridViewRow)ckBox.Parent.Parent;
if (ckBox.Checked)
{
// user just checked this box - un-check all
foreach (GridViewRow gvRow in gvChild.Rows)
{
if (gvRow.RowIndex != gvRowClick.RowIndex)
{
CheckBox ckRowBox = (CheckBox)gvRow.FindControl("ckSel");
ckRowBox.Checked = false;
}
}
}
}
A few things:
As noted, I dumped use of the gridv/listv event model. (we just pick up the grid view/listview row using sender.parent.
And we don't load the child grids until expanded - this is good for performance.
and if it been expanded, and we click "+" again, we hide, but if we re-expand, then we don't hit the database to re-load (and we don't want to, since if we did, then the checkbox would be lost).
And quite amazing? the lv/gv does retain its state for us. So expanded parts even survice the checkbox post back code.
I did not write out back to the database, but it would be quite simple code to then process each list-view row, then get the gv, and then get the checked row (PK ID) and then write that back to the database or do whatever if we wanted to on some button outside of this lv/gv.

How to preserve value of textboxes using TemplateFields in GridView

I have a GridView that lists data from my mysql database table. In addition, I created two TemplateFields to the GridView. The first TemplateField displays the data from database tables and the second TemplateView contains 1x asp:TextBox (a.k.a quantity) and 2x asp:Buttons (a.k.a +/- buttons which change the value inside the quantity TextBox. In addition to binding the GridView on PageLoad event, I also have a search TextBox which filters the rows displayed in the GridView. Here is the code behind for the search GridView TextBox:
private void SearchProducts()
{
string constr = ConfigurationManager.ConnectionStrings["default"].ConnectionString;
using (MySqlConnection con = new MySqlConnection(constr))
{
using (MySqlCommand cmd = new MySqlCommand())
{
string sql = "SELECT logic_code,description,image_location,product_group,supplier_number,sequence,unit_code,unit_of_price,location,sales_date,price_pref,special_price,in_stock,total_inventory,new_products FROM products";
if (!string.IsNullOrEmpty(txtSearch.Text.Trim()))
{
sql += " WHERE description LIKE " + "'%" + txtSearch.Text + "%'";
}
cmd.CommandText = sql;
cmd.Connection = con;
using (MySqlDataAdapter sda = new MySqlDataAdapter(cmd))
{
DataTable dt = new DataTable();
sda.Fill(dt);
GridView1.DataSource = dt;
dt.Columns.Add(new DataColumn("QUANTITY"));
GridView1.DataBind();
//TextBox qty4 = GridView1.FindControl("qty_ordered") as TextBox;
// for(int i = 0; i < GridView1.Rows.Count; i++)
//{
// Label test222 = (Label)GridView1.Rows[i].FindControl("test2");
// TextBox qty2 = (TextBox)GridView1.Rows[i].FindControl("qty_ordered");
// if (ViewState["purchased"] != null)
// {
// qty2.Text = ViewState["purchased"].ToString();
// }
// //test222.Text = qty2.Text;
//}
}
}
}
//foreach(GridViewRow rows in GridView1.Rows)
{
//Label test22 = rows.FindControl("test2") as Label;
//TextBox qty = rows.FindControl("qty_ordered") as TextBox;
//if (ViewState["purchased"] != null)
//{
//qty.Text = ViewState["purchased"].ToString();
//}
}
}
First I tried saving each Rows TextBox.Text to ViewState but wasn't successful, then I tried dynamically adding a new column to DataTable before DataBind() but that also went south... The Buttons (+/-) and TextBox work fine when PostBack is from the buttons themselves. However, as soon as I filter the GridView using the c# code above, The TextBoxes all turn back to "0" and lose their values. I think that adding the new column dynamically is the way to go, I'm just not sure how to save/update the values without creating EditTemplateFields.
Here is my asp.net code for the GridView:
<asp:GridView id="GridView1" EnableViewState="true" AutoGenerateColumns="false" PageSize="100" ShowHeader="false" DataKeyNames="logic_code" AllowPaging="true" runat="server" Style="width:100%;margin-top:45px;">
<Columns>
<asp:BoundField DataField="QUANTITY" runat="server" readonly="true" />
<asp:TemplateField HeaderText="Product_Template" runat="server">
<ItemTemplate>
<asp:label id="supplier_number" runat="server" Style="font-weight:bold;font-size:28px;" Text='<%# Eval("supplier_number")%>' /> <asp:label id="total_inventory" runat="server" Text='<%# Eval("total_inventory")%>' Style="float:right;" />
<br />
<asp:label id="sequence" runat="server" Text='<%# Eval("sequence")%>' Style="float:right;" />
<br />
<asp:Image id="product_image" runat="server" Height="320px" Width="320px" ImageUrl='<%# Eval("image_location")%>' />
<br />
<asp:label id="product_description" runat="server" Text='<%# Eval("description")%>' Style="white-space:nowrap;" /> &nbsp<asp:label id="unit_of_price" runat="server" Text='<%# Eval("unit_of_price")%>' Style="float:right;font-size:10px;margin-top:16px;margin-right:5px;margin-left:1px;" /><asp:label id="price_pref" runat="server" Text='<%# "$" + Eval("price_pref")%>' Style="float:right;font-size:22px;font-weight:bold;" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Product_Template1" runat="server" ItemStyle-Width="150px">
<ItemTemplate runat="server">
<asp:Button id="add" runat="server" Text="+" Width="45px" Style="float:right;" OnClick="addClicked" autopostback="true" UseSubmitBehavior="true"></asp:Button> <asp:Button id="subtract" runat="server" Text="-" Style="float:right;" OnClick="subtractClicked" autopostback="true" UseSubmitBehavior="true" Width="45px"></asp:Button>
<asp:TextBox id="qty_ordered" runat="server" Text="0" Enabled="false" Style="float:right;" Width="57px" EnableViewState="true" ReadOnly="true" />
<asp:Label id="unit_display" runat="server" Style="float:right;" />
<asp:Label id="sequenceID" runat="server" Text='<%# Eval("sequence")%>' Visible="false" Enabled="false" />
<asp:Label id="unit_code1" runat="server" Text='<%# Eval("unit_code")%>' Visible="false" Enabled="false" />
<asp:Label id="supplier_no" runat="server" Text='<%# Eval("supplier_number")%>' Visible="false" Enabled="false" />
<asp:Label id="total_inventory1" runat="server" Text='<%# Eval("total_inventory")%>' Visible="false" Enabled="false" />
<asp:Label id="logic_code1" runat="server" Text='<%# Eval("logic_code")%>' Visible="false" Enabled="false" />
<asp:Label id="unit_of_price1" runat="server" Text='<%# Eval("unit_of_price")%>' Visible="false" Enabled="false" />
<asp:Label id="price_pref1" runat="server" Text='<%# Eval("price_pref")%>' Visible="false" Enabled="false" />
<asp:Label id="special_price1" runat="server" Text='<%# Eval("special_price")%>' Visible="false" Enabled="false" />
<asp:Label id="description1" runat="server" Text='<%# Eval("description")%>' Visible="false" Enabled="false" />
<asp:Label id="tester" runat="server" Text='<%# Eval("description")%>' Visible="false" Enabled="false" />
<asp:Label id="test2" runat="server" Visible="true" Enabled="false" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Here is the code behind for how I populate the GridView on PageLoad when the GridView is not getting filtered by the search box:
private void BindGrid()
{
string constr = ConfigurationManager.ConnectionStrings["default"].ConnectionString;
using (MySqlConnection con = new MySqlConnection(constr))
{
con.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT logic_code,description,image_location,product_group,supplier_number,sequence,unit_code,unit_of_price,location,sales_date,price_pref,special_price,in_stock,total_inventory,new_products FROM products"))
{
using (MySqlDataAdapter da = new MySqlDataAdapter())
{
cmd.Connection = con;
da.SelectCommand = cmd;
using (DataTable dt = new DataTable())
{
da.Fill(dt);
GridView1.DataSource = dt;
dt.Columns.Add(new DataColumn("QUANTITY", System.Type.GetType("System.Double")));
GridView1.DataBind();
con.Close();
}
}
}
}
}
And PageLoad is here:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
BindGrid();
}
if (string.IsNullOrEmpty(txtSearch.Text))
{
//txtSearch.Attributes.Add("CssStyle", "cursor");
txtSearch.Attributes.Add("placeholder", " Showing All Products");
}
//foreach(GridViewRow row in GridView1.Rows)
//{
// if (IsPostBack)
// {
// if (ViewState["purchased"].ToString() != null)
// {
// qty.Text = ViewState["purchased"].ToString();
// }
// }
//}
}
I also have EnableViewState = "true" at the top of page.
***Note: with the code below on each button (+/-), the ViewState seems to save fine as my labels get populated appropriately by reading the ViewState even when postback. However, the values of the labels (ViewState value) get reset once I call the private void SearchProducts()
for(int i = 0; i < GridView1.Rows.Count; i++)
{
Label test222 = (Label)GridView1.Rows[i].FindControl("test2");
TextBox qty2 = (TextBox)GridView1.Rows[i].FindControl("qty_ordered");
ViewState["purchased"] = qty2.Text;
test222.Text = ViewState["purchased"].ToString();
}
and heres 2 snapshots: (as you can see, when I enter "Benus" inside the search textbox, the gridview gets filtered correctly, but all the TextBox values gets reset to "0")

Fail to save multiple data from gridview to database

Here is the HTML markup of the gridview.I mean aspx page
<asp:GridView ID="Gridview1" runat="server" ShowFooter="true" AutoGenerateColumns="false"
OnRowCreated="Gridview1_RowCreated" Height="145px">
<Columns>
<asp:BoundField DataField="RowNumber" HeaderText="Row Number" />
<asp:TemplateField HeaderText="Header 1">
<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="Header 3">
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" AppendDataBoundItems="true" DataTextField="CURRENCY_NAME"
DataValueField="CURRENCY_ID">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Header 4">
<ItemTemplate>
<asp:DropDownList ID="DropDownList2" runat="server" AppendDataBoundItems="true" DataTextField="BRAND_NAME"
DataValueField="BRAND_ID">
</asp:DropDownList>
</ItemTemplate>
<FooterStyle HorizontalAlign="Right" />
<FooterTemplate>
<asp:Button ID="ButtonAdd" runat="server" Text="Add New Row" OnClick="ButtonAdd_Click" />
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">Remove</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Button ID="BtnSave" runat="server" Text="Save All" OnClick="BtnSave_Click" />
<asp:Label ID="lblMessage" runat="server" Text=""></asp:Label>`
Here is the code behind to save the data into the database
private void InsertRecords(StringCollection sc)
{
StringBuilder sb = new StringBuilder(string.Empty);
string[] splitItems = null;
const string sqlStatement = "INSERT INTO GridViewDynamicData (Field1,Field2,Field3,Field4) VALUES";
foreach (string item in sc)
{
if (item.Contains(","))
{
splitItems = item.Split(",".ToCharArray());
sb.AppendFormat("{0}('{1}','{2}','{3}','{4}'); ", sqlStatement, splitItems[0], splitItems[1], splitItems[2], splitItems[3]);
}
}
using (OracleConnection strConn = GetConnection())
{
strConn.Open();
OracleCommand cmd = new OracleCommand(sb.ToString(), strConn);
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
lblMessage.Text = "Records successfully saved!";
}
}
protected void BtnSave_Click(object sender, EventArgs e)
{
int rowIndex = 0;
StringCollection sc = new StringCollection();
if (ViewState["CurrentTable"] != null)
{
DataTable dtCurrentTable = (DataTable)ViewState["CurrentTable"];
if (dtCurrentTable.Rows.Count > 0)
{
for (int i = 1; i <= dtCurrentTable.Rows.Count; i++)
{
//extract the TextBox values
TextBox box1 = (TextBox)Gridview1.Rows[rowIndex].Cells[1].FindControl("TextBox1");
TextBox box2 = (TextBox)Gridview1.Rows[rowIndex].Cells[2].FindControl("TextBox2");
DropDownList ddl1 = (DropDownList)Gridview1.Rows[rowIndex].Cells[3].FindControl("DropDownList1");
DropDownList ddl2 = (DropDownList)Gridview1.Rows[rowIndex].Cells[4].FindControl("DropDownList2");
//get the values from TextBox and DropDownList
//then add it to the collections with a comma "," as the delimited values
sc.Add(string.Format("{0},{1},{2},{3}", box1.Text, box2.Text, ddl1.SelectedItem.Text, ddl2.SelectedItem.Text));
rowIndex++;
}
//Call the method for executing inserts
InsertRecords(sc);
}
}
}
My database table is here
CREATE TABLE ERP.GRIDVIEWDYNAMICDATA
(
FIELD1 VARCHAR2(500 BYTE),
FIELD2 VARCHAR2(500 BYTE),
FIELD3 VARCHAR2(500 BYTE),
FIELD4 VARCHAR2(500 BYTE)
)
When I am running this project it is showing error "ORA-00911: invalid character". I don't know what is wrong. Any help will be appreciated.
I am not having enough reputation to comment, so I am posting my research as an answer.
Most probable cause is using ; in query building.
Remove ;(semi-colon) from the end of SQL string.
From the SQL query you are building from the code.
With semicolon (May causing the error)
sb.AppendFormat("{0}('{1}','{2}','{3}','{4}'); ", sqlStatement, splitItems[0], splitItems[1], splitItems[2], splitItems[3]);
Without Semicolon (Should try this)
sb.AppendFormat("{0}('{1}','{2}','{3}','{4}') ", sqlStatement, splitItems[0], splitItems[1], splitItems[2], splitItems[3]);
Or
Your string may not have straight ' single quotes. Try to write that again. (It seems OK though in your code posted along with question. But nothing wrong in verifying.)
References:
ORA-00911: invalid character
https://community.oracle.com/thread/2511511
http://www.oracle.com/webfolder/technetwork/tutorials/obe/db/hol08/dotnet/getstarted-c/getstarted_c_otn.htm

Re-populating checkboxlist in Edit Mode from SQL comma-separated string is not selecting checkboxes

I am not able to pre-populate CheckBoxList3 in my app. I have successfully retrieved string data from database and passed to array but routine fails with:
NullReferenceException:Object not set to instance of an object error at line:
ListItem currentCheckBox = cb3.Items.FindByValue(items[i].ToString());
readMyString() method uses SqlDataReader to read and split a string column from SQL table then pass the values for example: "A, B, C" to string array to identify which of 6 checkboxes should be selected. Code reference: [http://mikesdotnetting.com/Article/53/Saving-a-user's-CheckBoxList-selection-and-re-populating-the-CheckBoxList-from-saved-data]
HTML CODE:
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" CellPadding="4" DataKeyNames="MyID"
DataSourceID="sdsmyTable1" ForeColor="#333333" GridLines="None"
onrowdeleted="GridView1_RowDeleted"
onrowdeleting="GridView1_RowDeleting"
onrowupdated="GridView1_RowUpdated"
onrowupdating="GridView1_RowUpdating"
onselectedindexchanged="GridView1_SelectedIndexChanged"
onrowediting="GridView1_RowEditing"
onrowcancelingedit="GridView1_RowCancelingEdit"
onrowdatabound="GridView1_RowDataBound">
<RowStyle BackColor="#EFF3FB" />
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:BoundField DataField="myID" HeaderText="myID" ReadOnly="True"
SortExpression="myID" />
<asp:BoundField DataField="Date1" HeaderText="Date driver lic issued"
SortExpression="Date1" />
<asp:TemplateField HeaderText="chooseOne" SortExpression="chooseOne">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("chooseOne") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:RadioButtonList ID="RadioButtonList2" runat="server" SelectedValue='<%# Bind("chooseOne") %>' Font-Size="Small"
RepeatDirection="Horizontal">
<asp:ListItem Value="1">1</asp:ListItem>
<asp:ListItem Value="2">2</asp:ListItem>
<asp:ListItem Value="3">3</asp:ListItem>
</asp:RadioButtonList>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="MyCommaSeparatedString" SortExpression="MyCommaSeparatedString">
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("MyCommaSeparatedString") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("MyCommaSeparatedString") %>'></asp:TextBox>
<asp:CheckBoxList ID="CheckBoxList3" runat="server" Font-Size="Small"
RepeatDirection="Horizontal">
<asp:ListItem Value="A">A</asp:ListItem>
<asp:ListItem Value="B">B</asp:ListItem>
<asp:ListItem Value="C">C</asp:ListItem>
<asp:ListItem Value="D">D</asp:ListItem>
<asp:ListItem Value="E">E</asp:ListItem>
<asp:ListItem Value="F">F</asp:ListItem>
</asp:CheckBoxList>
</EditItemTemplate>
C# Code:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//// establish a datarow to dig into its minutia
DataRowView drv = e.Row.DataItem as DataRowView;
// if 1: RowType of gridview control is a datarow
if (e.Row.RowType == DataControlRowType.DataRow)
{
//if 2: is datarow in edit mode
if ((e.Row.RowState & DataControlRowState.Edit) > 0)
{
RadioButtonList rb2 = (RadioButtonList)e.Row.FindControl("RadioButtonList2");
CheckBoxList cb3 = (CheckBoxList)e.Row.FindControl("CheckBoxList3");
//CheckBoxList cb3 = (CheckBoxList)GridView1.Rows[GridView1.EditIndex].FindControl("CheckBoxList3");
CheckBoxList cb4 = (CheckBoxList)e.Row.FindControl("CheckBoxList4");
// Create an instance of SqlConn class
SqlConnClass getMyStr= new SqlConnClass();
//Return datareader to read Endorsements column from database
SqlDataReader rdr = getMyStr.selectMyString(GetMyID());
try
{
// column
if (rb2 != null)
{
rb2.SelectedValue = drv[2].ToString();
}
// column
//CheckBoxList cb3 = (CheckBoxList)e.Row.FindControl("CheckBoxList3");
if (cb3 != null)//if (cb3 contains 6 checkboxes (I, N, H, X, T, K)
{
//bind checkbox manually
cb3.DataSource = sdsDatasource;
cb3.DataTextField = "MyCommaSeparatedString ";
cb3.DataValueField = "MyCommaSeparatedString ";
cb3.DataBind();
// if row exists
if (rdr.HasRows)//(dt.Rows.Count > 0 && dt != null)
{
//start reading
rdr.Read();
//extract comma separated string from datareader into one-dimensional array
string[] items = rdr.GetString(0).Split(',');
//returns the upper bound for the indexes of the first dimension of the Array
for (int i = 0; i <= items.GetUpperBound(0); i++)
{
// currentCheckBox IS WHERE NULL OCCURS:
ListItem currentCheckBox = cb3.Items.FindByValue(items[i].ToString());
if (currentCheckBox != null)
{
currentCheckBox.Selected = true;
}
//cb3.SelectedValue = drv[3].ToString();
//}
}// end of for
//close SqlDataReader
rdr.Close();
}
// column
//CheckBoxList cb4 = (CheckBoxList)e.Row.FindControl("CheckBoxList4");
if (cb4 != null)
{
cb4.SelectedValue = drv[4].ToString();
}
}// end of if
}// end of try
catch (IndexOutOfRangeException ex2)
{
System.Diagnostics.Debug.WriteLine(ex2.Message + "; " + ex2.Source + "; " + ex2.TargetSite);
}//end of catch
}// end of if (rowstate)
} // end of if (rowtype)
}// end of method
What I have tried: calling readMyString() method from GridView1_RowDataBound event and/or from GridView1_RowEditing event.
Since CheckBoxList3 is empty to begin with and seems to not want to be null, I added the line cb3.Items[i].Value = items[i]; but the error just moves to the new line instead. I must be missing something.
Can anyone see where I've errored? I must be putting the code in the wrong methods...?
You are trying to find the control in the GridView. The controls are inside the GridView Rows.
So you need to do something like this:
CheckBoxList cb3 = (CheckBoxList) GridView1.Rows[GridView1.EditIndex].FindControl("CheckBoxList3");
Trim the items[i] like below:
ListItem currentCheckBox = cb3.Items.FindByValue(items[i].Trim());

add columns to the right in gridview

I have a grid view and when i click on the radiobutton approve it should update the recommend tag value to 1 based on the employeeID.However I am getting an error saying that object is not set to an instance of an object..My columns are also being added to the left..instead of right..Below is the code I have tried.
C# code
public void GridViewBind()
{
dadapter = new SqlDataAdapter("SELECT M_Emp_Personal.EmpName, M_Division.DivShort, M_Designation.DesigShort, T_TADA_tempform.BasicSalary, T_TADA_tempform.GPFNo, T_TADA_tempform.Gradepay,T_TADA_tempform.move_date, T_TADA_tempform.purpose, M_City.CityDesc, T_TADA_tempform.estt_visited, T_TADA_tempform.duration_stay, M_mode.mode_type, T_TADA_tempform.duration_unit, T_TADA_tempform.place, T_TADA_tempform.authority, T_TADA_tempform.exp_debited, T_TADA_tempform.reason FROM T_TADA_tempform INNER JOIN M_Emp_Personal ON T_TADA_tempform.EmpID = M_Emp_Personal.EmpID INNER JOIN M_Division ON T_TADA_tempform.DivisionID = M_Division.DivisionID INNER JOIN M_Designation ON M_Emp_Personal.DesigID = M_Designation.DesigID INNER JOIN M_City ON T_TADA_tempform.CityID = M_City.CityID INNER JOIN M_mode ON T_TADA_tempform.mode_ID = M_mode.mode_ID where M_Emp_Personal.EmpID=" + ddlname.SelectedValue + "", conn);
dset = new DataSet();
dadapter.Fill(dset);
GridView1.DataSource = dset.Tables[0];
GridView1.DataBind();
}
protected void submit_info(object sender, EventArgs e)
{
GridViewRow grow = (GridViewRow)(sender as Control).Parent.Parent;
RadioButton rbpApprove = (RadioButton)grow.FindControl("rbtnapprove");
RadioButton rbpReject = (RadioButton)grow.FindControl("rbtnreject");
if (rbpApprove.Checked == true)
{
conn.Open();
SqlCommand cmd = new SqlCommand("UPDATE T_TADA_tempform SET Recommened_tag =1 where EmpID=#EmpID", conn);
cmd.Parameters.AddWithValue("#EmpID", ddlname.SelectedValue);
conn.Close();
}
this is my ASP.NET code
<asp:GridView ID="GridView1" runat="server" CssClass="vutblrow" TabIndex="6"
CellPadding="4" ForeColor="#333333" GridLines="None" Width="100%"
PagerStyle-Mode="NumericPages" >
<PagerStyle CssClass="pgr" Height="25px" BorderStyle="Solid" />
<Columns>
<asp:TemplateField HeaderText="Approve">
<ItemTemplate>
<asp:RadioButton runat="server" GroupName="status" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Reject">
<ItemTemplate>
<asp:RadioButton runat="server" GroupName="status" />
</ItemTemplate>
</asp:TemplateField><asp:TemplateField HeaderText="Submit">
<ItemTemplate>
<asp:Button CssClass="btnAction" Text="Sumbit" runat="server" OnClick="submit_info" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle CssClass="vutblhdr" />
</asp:GridView>
You will see that error when you're trying to use an object that hasn't been initialised correctly.
Likely candidates are:
RadioButton rbpApprove = (RadioButton)grow.FindControl("rbtnapprove");
RadioButton rbpReject = (RadioButton)grow.FindControl("rbtnreject");
If the rbpApprove Control isn't found then this line here:
if (rbpApprove.Checked == true)
Will give you the error you are getting.
However only seeing a subset of your code it could be elsewhere.
I think you are missing the Ids of the radionbuttons, try this
<asp:TemplateField HeaderText="Approve">
<ItemTemplate>
<asp:RadioButton ID="rbtnapprove" runat="server" GroupName="status" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Reject">
<ItemTemplate>
<asp:RadioButton ID="rbtnreject" runat="server" GroupName="status" />
</ItemTemplate>
</asp:TemplateField>
And call Execute
if (rbpApprove.Checked == true)
{
conn.Open();
SqlCommand cmd = new SqlCommand("UPDATE T_TADA_tempform SET Recommened_tag =1 where EmpID=#EmpID", conn);
cmd.Parameters.AddWithValue("#EmpID", ddlname.SelectedValue);
cmd.ExecuteNonQuery();
conn.Close();
}

Categories

Resources