c# Cannot Convert from string to int - c#

I have a gridview that populates from an SQL table and shows two columns, one comes from an integer data column, the other from an nvarchar. Gridview also has a checkbox column
The gridview populates correctly, and after a subset of rows is selected (via checkbox column) I want to insert the selected rows into another SQL table. When populating the variables for the SQL statement however I get the "Cannot Convert from string to int" error on the value that is populated from an int to begin with.
I have tried writing up convert and parse for this statement but still getting the error:
cmd.Parameters.AddWithValue("#PracticeArea", int.Parse(row.Cells["Id"].Value));
cmd.Parameters.AddWithValue("#PracticeArea", Convert.ToInt32(row.Cells["Id"].Value));
cmd.Parameters.AddWithValue("#PracticeArea", Convert.ToInt32(row.Cells["Id"].Text));
All still show the error on the ["Id"] value.
Any thoughts?
Example of the data that is being populated to the gridview is:
PracticeID PracticeName
1 General Surgical Pathology
2 General Pathology/Basic Science
4 Cardiovascular
6 Cytopathology-GYN
7 Cytopathology-nonGYN
Full button command is:
protected void Bulk_Insert(object sender, EventArgs e)
{
foreach (GridViewRow row in GridView1.Rows)
{
if ((row.FindControl("CheckBox1") as CheckBox).Checked)
{
string connectionString = WebConfigurationManager.ConnectionStrings["CS1"].ConnectionString;
SqlConnection con = new SqlConnection(connectionString);
{
using (SqlCommand cmd = new SqlCommand("INSERT INTO ReviewerPractice VALUES(#Reviewer, #PracticeArea)", con))
{
cmd.Parameters.AddWithValue("#Reviewer", ReviewerName.Text);
cmd.Parameters.AddWithValue("#PracticeArea", Convert.ToInt32(row.Cells["Id"].Value));
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
}
}
Full Gridview control is:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Id" HeaderText="Id" ItemStyle-Width="30" />
<asp:BoundField DataField="PracticeName" HeaderText="PracticeName" ItemStyle-Width="150" />
</Columns>
</asp:GridView>
<br />
<asp:Button ID="Button1" Text="Add Practice Areas" OnClick="Bulk_Insert" runat="server" />
Hope this answers (some?) of the questions from all the comments to date.

The problem is that row.Cells[] is an array, so you need to use it like this:
row.Cells[3].Text
And it's better to use the Parameters for sql like this:
cmd.Parameters.Add("#PracticeArea", SqlDbType.Int).Value = Convert.ToInt32(row.Cells[index].Text;

Related

How can I get the distinct values in a Gridview column and store them into a Datatable or list?

I have a Gridview in a C# ASPX Page called Gridview1 that pulls a Table from a SQL Server and displays it on PageLoad.
There are 10 columns in the Gridview and I need all the distinct values in column 7 which is Code
Code
A
C
D
A
A
D
B
E
R
A
A
C
B
Basically I need some kind of structure, list or even a datatable to get all the distinct values from the Column "Code". From the example above it would be a list or datatable with 6 entries since there are 6 unique codes in the Gridview column.
Distinct
A
B
C
D
E
R
Any ideas how this can be implemented?
Well, ALWAYS but always try to do such code against the data source and NOT the web page HTML (be it a list view, or grid view, repeater or whatever). The web page is for display of the data, not data base stuff.
Now, I suppose in this case, we could operate against the grid, but it usually a WHOLE lot easier to operate against the data.
So, say this grid:
<div style="float:left;width:40%">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"
CssClass="table table-hover table-striped"
DataKeyNames="ID">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:Button ID="cmdDel" runat="server"
Text="Delete"
CssClass="btn"
onclick="cmdDel_Click"
onclientClick="return confirm('really delete this?');"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
<div style="float:left;margin-left:40px">
<h4>City list</h4>
<asp:ListBox ID="ListBox1" runat="server"
DataTextField="City"
DataValueField="City" Width="163px" Height="159px"
></asp:ListBox>
</div>
</div>
So, right next to the grid, I have a list box we will list out each seperate city.
So, code to load is this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
DataTable rstData = MyRst("SELECT * FROM tblHotelsA ORDER BY HotelName");
GridView1.DataSource = rstData;
GridView1.DataBind();
// now fill out a list box of each city
DataTable rstCity = new DataTable();
rstCity = rstData.DefaultView.ToTable(true, "City");
rstCity.DefaultView.Sort = "City";
ListBox1.DataSource = rstCity;
ListBox1.DataBind();
}
And we get this:
So, NOTE how we went to the data source - NOT the grid (the grid is not a database and in most cases we should not think of the grid as such).
However, we could also pull the values out of the grid (can't see why we would do this).
So, lets drop in listbox 2, and add this code that operates against the grid:
our 2nd listbox - this time NOT data bound.
So, this:
<div style="float:left;margin-left:40px">
<h4>City list 2nd example</h4>
<asp:ListBox ID="ListBox2" runat="server"
DataTextField="Text"
DataValueField="Value"
Width="163px" Height="159px"
></asp:ListBox>
</div>
And say a button click or whatever - we run this code to fill out 2nd listbox from the data grid.
FYI:
If you using templated fields, then you have to use findcontrol to get the control.
If you using data fields, then you use .cells[] array/collection.
but, CAUTION, since empty cells will render as a non breaking space &nsb;
So, we convert from html, just to be save, and we have this code:
protected void Button1_Click1(object sender, EventArgs e)
{
List<string> CityList = new List<string>();
foreach (GridViewRow gRow in GridView1.Rows)
{
string sCity = Server.HtmlDecode(gRow.Cells[2].Text);
if (!CityList.Contains(sCity))
CityList.Add(sCity);
}
// display our list in 2nd listbox
CityList.Sort();
foreach (string sCity in CityList)
{
ListBox2.Items.Add(new ListItem(sCity, sCity));
}
}
So, now we have this:
So try to operatee against the data. I mean, we could even say get a list of distinct citys wiht a query, say this:
string strSQL = "SELECT City from tblHotels GROUP BY City";
Datatable rstCity = MyRst(strSQL);
ListBox1.DataSource = rstCity;
ListBox1.DataBind();
So, in most cases??
Much less effort and better to get this data from the data source, and NOT go to the GV - as it is a display and render system - not a data base, nor is it a data source.
Now, in above, I used a helper function MyRst. All that does is return a table based on sql - (became VERY tired very fast having to type that type of code over and over). So that was this:
DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}

Dropdownlist based on database and to merge column when they have same ID

I have the examples of data saved in the database as shown in the figure:
list of attachments uploaded by 3 different users (STAFF_145, STAFF_143 and STAFF_147)
When I called it from gridview list, it shows like this:
Gridview of list attachment
Based on the gridview, I tried to apply the "Attachments & TRF" column with <asp:Label ID="txt_training_attach_name" runat="server" Text='<%# Bind("training_attach_name") %>' ReadOnly="true">.
It shows error when I've change to "Dropdownlist" instead of using "Label" or "Textbox".
System.ArgumentOutOfRangeException: ''txt_training_attach_name' has a
SelectedValue which is invalid because it does not exist in the list
of items. Parameter name: value'
The error points out at here when I used Dropdownlist:
if (dt.Rows.Count > 0)
{
Grid_Attachment.DataSource = dt;
Grid_Attachment.DataBind();
}
It is possible if I want to make a gridview as shown as like this?
Dropdownlist and Merge Column
I've try many ways since last month but I still cannot get the answer. Appreciate if you could help me. Thank you in advanced.
You don't mention if the staff table of up-loaded files is a different table then the one that supposed to drive the grid.
if it is for some reason, then build a group by query that does not include the file(s) column, and group by so you wind up with a SINGLE row for each staff member.
So, then we can drop in a grid list this:
And I am going to use a listbox in place of a combo (dropdown), so it will NICE display the files - you can change that to a dropdown if you want - same code
So, the markup might be this:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table table-hover" OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:BoundField DataField="Firstname" HeaderText="First Name" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" />
<asp:BoundField DataField="TrainingDate" HeaderText="Training Date" DataFormatString="{0:yyyy-MM-dd}" />
<asp:BoundField DataField="ApplicationDate" HeaderText="Application Date" DataFormatString="{0:yyyy-MM-dd}" />
<asp:BoundField DataField="ProgramTitle" HeaderText="Program Title" />
<asp:BoundField DataField="TrainingCost" HeaderText="Training Cost" DataFormatString="{0:c}" />
<asp:TemplateField HeaderText="Documents Submitted">
<ItemTemplate>
<asp:ListBox ID="cboFiles" runat="server" Width="200PX"
DataTextField ="FileName"
DataValueField="FileName">
</asp:ListBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Note how we added a listbox (as noted, use a drop down if you want).
So, the code to fill this gv would thus be this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
GridView1.DataSource = MyRst("SELECT * from Users ORDER BY FirstName");
GridView1.DataBind();
}
DataTable MyRst(string strSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
However, for each row, we need to load up the list of files for that one row. As noted, I don't know if you have two tables here - or one. (but, it really does not matter - as noted, use a group-by for this main grid data source.
Now, the only extra part is to use the gv "row data bound" event. This fires for each row during render, and is the idea event to load up the combo or list box.
That code is thus this:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// get PK row id (user id)
int? PKID = GridView1.DataKeys[e.Row.RowIndex]["ID"] as int?;
string strSQL = "SELECT FileName FROM MyFiles WHERE User_ID = " + PKID;
DataTable rstFiles = MyRst(strSQL);
ListBox cboFiles = e.Row.FindControl("cboFiles") as ListBox;
cboFiles.DataSource = rstFiles;
cboFiles.DataBind();
cboFiles.Rows = 1;
if (rstFiles.Rows.Count > 1)
cboFiles.Rows = rstFiles.Rows.Count;
}
}
And above I do have two columns. One is JUST file name, and one column is the full path name + file to the up-load folder. If you don't have just a file name column, then we can write a bit of code to JUST include + show file name.
the results of running the above is thus this:

GridView Remove one definition

I'm trying to create a web page with the aps.net framework and I connect to the SQL server successfully and I want to display the data from the database in the Grid View and there are a search box and dropdown list but there is an error when I try to search
this is the error message:
Both DataSource and DataSourceID are defined on 'GridView1'. Remove one definition.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Both DataSource and DataSourceID are defined on 'GridView1'. Remove one definition.
and my code viewpage1.aspx
the GridView
<asp:GridView ID="GridView1" runat="server" BackColor="White" BorderColor="#999999" BorderStyle="Solid" BorderWidth="1px" CellPadding="3" ForeColor="Black" GridLines="Vertical" OnSelectedIndexChanged="GridView1_SelectedIndexChanged" Format="dd/MM/yyyy" AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="InvoiceID" DataSourceID="SqlDataSource3">
<AlternatingRowStyle BackColor="#CCCCCC" />
-and this the sqldatasource
<asp:SqlDataSource ID="SqlDataSource3" runat="server" ConnectionString="<%$ ConnectionStrings:connStr %>" SelectCommand="Select * from [Portal].[fn_GetInvoices] (#SearchText) where CompanyCode=#CompanyCode and InvoiceDate between #fromDate and #toDate">
<SelectParameters>
viewpage1.aspx.cs
sqlcomm.CommandText = sqlquery;
sqlcomm.Connection = sqlconn;
DataTable dt = new DataTable();
SqlDataAdapter adapter = new SqlDataAdapter(sqlcomm);
adapter.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
This is a common error message.
I OFTEN use the wizards to build a gridview I use this:
From above, I choose create new data source.
I let the wizard run.
BUT THEN we wind up with some MESSAY sqldatasource in the web page. I do NOT like them, and they NEAR ALWAYS just cause you pain.
So, what I will then do this:
Remove the sqldata source from the web markup - you don't' need that mess anyway.
eg this:
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:CSharpWebApp.Properties.Settings.TEST4 %>"
SelectCommand="SELECT [ID], [Fighter], [Engine], [Thrust], [Description], [ImagePath]
FROM [Fighters]"></asp:SqlDataSource>
DELETE the above!!!!
Now WHEN you WILL use code to load up the Gridview? Then you ALSO must turn off (remove) the fact that you NOT GOING to use the sql data source anymore.
So in your GV, remove this:
So, all that error message is telling you is you are trying to set the data source in "code" but you ALREADY have a sql datasource setup in the markup.
So, get in the habit of blowing out and removing the sqldata source on the page, and ALSO remove the GV data source setting in the markup.
So, now say I will have this GV, and NOT have ANY data source in the markup in the web page. (and I recommend you do this). So, I still VERY often use the wizards. Even for a dropdown list, a gridview, repeaters, and even listview (my favorite).
So, run wizards - build the markup
Then blow out (remove) the SqlDataSource, and the
DataSourceID="SqlDataSource1" from the control (in this case gv).
So, as noted, you cannot have BOTH a DataSourceID="SqlDataSource1" and THEN try to use code. It is one or the other - and that's what the error message is telling you.
So, now we have this markup:
(and the wizards generated most of this for me!!!)
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table" >
<Columns>
<asp:BoundField DataField="Fighter" HeaderText="Fighter" />
<asp:BoundField DataField="Engine" HeaderText="Engine" />
<asp:BoundField DataField="Thrust" HeaderText="Thrust" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="View">
<ItemTemplate>
<asp:ImageButton ID="btnImage" runat="server" Height="68px" Width="149px"
OnClientClick ="popimage(this);return false"
ImageUrl = '<%# Eval("ImagePath") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Just nice clean markup - no Sqldatasource junk.
Now we are free to write normal code like a normal human, and we can fill the grid like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from Fighters", conn))
{
conn.Open();
DataTable rstData = new DataTable();
rstData.Load(cmdSQL.ExecuteReader());
GridView1.DataSource = rstData;
GridView1.DataBind();
}
}
}
And our results are now this:
Ok, so now lets add a search box above the GV to search the GV.
Say you can type in the first few chars of the Fighter jet name, and we want to filter by that:
So, drop in a text box above the GV, + search button.
We now have say this:
<asp:Label ID="Label1" runat="server" Text="Search for Fighter jet" Font-Size="Large"></asp:Label>
<asp:TextBox ID="txtSearch" runat="server" Style="margin-left:15px" Font-Size="Large"></asp:TextBox>
<asp:Button ID="cmdSearch" runat="server" Text="search"
style="margin-left:15px" CssClass="btn"
/>
<br />
<br />
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table" >
<Columns>
So, now the page with searching looks like this:
Say we search for Lockheed - but even just typing in Lock would be fine.
thus:
And now our code can say be this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid("");
}
void LoadGrid(string MySearch)
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from Fighters ", conn))
{
if (MySearch != "")
{
cmdSQL.CommandText += #" WHERE Fighter LIKE #Fighter + '%'";
cmdSQL.Parameters.Add("Fighter", SqlDbType.NVarChar).Value = MySearch;
}
conn.Open();
DataTable rstData = new DataTable();
rstData.Load(cmdSQL.ExecuteReader());
GridView1.DataSource = rstData;
GridView1.DataBind();
}
}
}
protected void cmdSearch_Click(object sender, EventArgs e)
{
LoadGrid(txtSearch.Text);
}
}
So, I am STRONG suggesting that you DUMP the sqldata source on the web page markup. Such Sqldata soruces on the page can be great for one time load or data display. But the VERY instant you want control, filters, and need to use code?
Quite much the SAME instant it is time to drop and toss out and remove the data source from the web markup. You be glad you did, and as you can see, you now have 100% EASY AND SIMPLE control of the data you shove into the GV, and that includes endless possible use of simple code and buttons to add filters etc. to that data.

Submitting multiple rows in gridview with Checkboxes (C#)

I am aiming to get data:
From an sql database
To a gridview
To a local table
So far, I am able to use a stored procedure to display the sql data to a gridvew and I am also able to use checkboxes to send the data to a local table.
Issue:
Only one row's data is being submitted to the table, despite the number of checkboxes checked.
ex. I click 3 checkboxes, wanting to get 3 different rows of data to the table. I hit the submit button and when I check the table, only one of the "checked" rows is submitted to the table 3 times.
EDITED Code:
protected void btnSubmit_Click(object sender, EventArgs e)
{
string connectionString = ConfigurationManager.ConnectionStrings["localDataB"].ConnectionString;
using (var sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
string insertStatement = "INSERT into LocalDB (Item1, Item2, Item3)" + "(#Item1, #Item2, #Item3)";
string Data1, Data2;
float Data3;
foreach (GridViewRow gRow in GridView1.Rows)
{
CheckBox ckSel = (gRow.FindControl("checker") as CheckBox);
if (ckSel.Checked)
{
Data1 = Convert.ToString(gRow.Cells[1].Text);
Data2 = Convert.ToString(gRow.Cells[2].Text);
Data3 = Convert.ToInt32(gRow.Cells[3].Text);
using (var sqlCommand = new SqlCommand(insertStatement, sqlConnection))
{
sqlCommand.Parameters.Add("Item1", SqlDbType.Text).Value = Data1;
sqlCommand.Parameters.Add("Item2", SqlDbType.Text).Value = Data2;
sqlCommand.Parameters.Add("Item3", SqlDbType.Float).Value = Data3;
sqlCommand.ExecuteNonQuery();
}
}
}
}
GVbind();
Code for checkbox inside grid:
<asp:GridView ID="GridView1" runat="server" EmptyDataText="No Data Found" BackColor="#CCCCCC" BorderColor="#999999" BorderStyle="Solid" BorderWidth="3px" CellPadding="4"
AutoGenerateColumns="False" CellSpacing="2" ForeColor="Black" DataKeyNames="Data1" Width="70%" Visible="False" ShowFooter="True">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<asp:Label ID="SelectBox" runat="server" Text="Select"></asp:Label>
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="checker" runat="server" OnCheckedChanged="checker_CheckedChanged"/>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Data1" HeaderText="Title1" ReadOnly="True" />
<asp:BoundField DataField="Data2" HeaderText="Title2" ReadOnly="True" />
<asp:BoundField DataField="Data3" HeaderText="Title3" />
</Columns>
</asp:GridView>
Ok, it not at all clear what your routine checker_CheckedChanged() does?
You don't need a post-back or anything for the check boxes - but ONLY the one submit button and code stub
. Those data1, data2 etc. will NOT persist in memory anyway. So, you can't use that routine - but you don't need it either.
Unless the grid has multiple pages etc., then dump that routine. You are free to check box any row in the grid. You then have one submit button code, and that routine just needs a bit of change to check all GV rows, and save the check box values.
That submit button code thus can/will look like this:
protected void btnSubmit_Click(object sender, EventArgs e)
{
string connectionString = ConfigurationManager.ConnectionStrings["localDataB"].ConnectionString;
using (var sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
// insert any row with check boxes into temp db
string insertStatement = "INSERT into LocalDB (Item1, Item2, Item3) " +
"values (#Item1, #Item2, #Item3)";
bool Data1, Data2, Data3;
foreach (GridViewRow gRow in GridView1.Rows)
{
Data1 = Convert.ToBoolean(gRow.Cells[0].ToString());
Data2 = Convert.ToBoolean(gRow.Cells[1].ToString());
Data3 = Convert.ToBoolean(gRow.Cells[2].ToString());
// save data if ANY is checked
if (Data1 | Data2 | Data3)
{
using (var sqlCommand = new SqlCommand(insertStatement, sqlConnection))
{
sqlCommand.Parameters.Add("#Item1", SqlDbType.Bit).Value = Data1;
sqlCommand.Parameters.Add("#Item2", SqlDbType.Bit).Value = Data2;
sqlCommand.Parameters.Add("#Item3", SqlDbType.Bit).Value = Data3;
sqlCommand.ExecuteNonQuery();
}
}
}
}
GVbind();
}
I don't see the need for your first routine. The submit button can loop the GV, get the check box values, and if any one of the 3 is checked, then you do the insert.
However, keep in mind that the cells[] collection ONLY works for datafields if you using a templated control and REAL check box, then you need to use findcontrol, and NOT the cells[] collection
Edit:
Ok, first, information provided suggests that a template field is being used.
HOWEVER, we will first address the CheckBoxField code, since it HARD to google and find that answer. So I going to include that answer.
If a check box is a datafield, then you can't change/edit, but you STILL MAY want to iterate over the GV, and get those values.
So, for data fields, say like this:
<asp:CheckBoxField DataField="Active" HeaderText="Active" />
Then our code has to work like this (you have to dig deeper into cells() colleciton.
So, code becomes this:
foreach (GridViewRow gRow in GridView1.Rows)
{
Data1 =(gRow.Cells[0].Controls[0] as CheckBox).Checked;
Data2 = (gRow.Cells[1].Controls[0] as CheckBox).Checked;
Data3 = (gRow.Cells[2].Controls[0] as CheckBox).Checked;
Note how a CheckBoxField requires us to use controls.
However, as noted, with template field (any kind and ANY of them?).
WE DO NOT use the Cells[] collection and templated columns DO NOT appear in the cells collection.
And thus, in a lot (probably most) cases, then we can expect to have a CheckBox control dropped into the markup as a templated field.
Typical looks like this:
<asp:GridView ID="GridView1" runat="server" class="table borderhide"
AutoGenerateColumns="false" DataKeyNames="ID">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" HeaderStyle-Width="200" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Smoking" ItemStyle-HorizontalAlign="Center" >
<ItemTemplate>
<asp:CheckBox ID="chkSmoking" runat="server"
Checked='<%# Eval("Smoking") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Balcony" ItemStyle-HorizontalAlign="Center" >
<ItemTemplate>
<asp:CheckBox ID="chkBalcony" runat="server"
Checked='<%# Eval("Balcony") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
So in above, the first values (bound fields) WILL BE found in cells colleciton.
However, the templated fields above? we have to do this:
"WHERE ID = #ID";
foreach (GridViewRow gRow in GridView1.Rows)
{
CheckBox cSmoke = (CheckBox)gRow.FindControl("chkSmoking");
CheckBox cBlacony = (CheckBox)gRow.FindControl("chkBalcony");
int PKID = (int)GridView1.DataKeys[gRow.RowIndex]["ID"];
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
cmdSQL.Parameters.Add("#S", SqlDbType.Bit).Value = cSmoke.Checked;
cmdSQL.Parameters.Add("#B", SqlDbType.Bit).Value = cBlacony.Checked;
cmdSQL.Parameters.Add("#ID", SqlDbType.Int).Value = PKID;
cmdSQL.ExecuteNonQuery();
}
}
So, our code then becomes this:
foreach (GridViewRow gRow in GridView1.Rows)
{
Data1 =(gRow.FindControl("Active") as CheckBox).Checked;
Data2 = (gRow.FindControl("Smoking") as CheckBox).Checked;
Data3 = (gRow.FindControl("Balcony") as CheckBox).Checked;
Now of course, you replace the "Text control" id with YOUR data 1, 2, and 3 id that you used.
The rest of the code should be the same.
BIG LESSON OF THE DAY?
Post a wee bit of markup - not a huge boatload - but just a few lines next time. You save world poverty, and I would have been able to post a better answer next time.
So the rule is:
DataBound fields - use cells[] collection.
Templated fields - you have to using .FindControl("name of control id goes here")
Edit#2
Ok, so far, the question is now this:
We have some data. If the user checks the row 1, or 5 or 10 rows, for each of the checked rows, I want to write out the columns/values I have in 3 other columns item1, item2, item3?
Simple queston!!!!
Ok, so the ONLY missing information is WHAT data type field type is item1, item2, and item3? We only really are missing that part.
So, if check box = true, write out those 3 item columns to the new temp table.
So, the code now should be:
bool Data1, Data2, Data3;
foreach (GridViewRow gRow in GridView1.Rows)
{
// get check box -
CheckBox ckSel = (gRow.FindControl("checker") as CheckBox);
// save data if ANY is checked
if (ckSel.Checked)
{
Data1 = Convert.ToBoolean(gRow.Cells[0].Text);
Data2 = Convert.ToBoolean(gRow.Cells[1].Text);
Data3 = Convert.ToBoolean(gRow.Cells[2].Text);
using (var sqlCommand = new SqlCommand(insertStatement, sqlConnection))
{
sqlCommand.Parameters.Add("#Item1", SqlDbType.Bit).Value = Data1;
sqlCommand.Parameters.Add("#Item2", SqlDbType.Bit).Value = Data2;
sqlCommand.Parameters.Add("#Item3", SqlDbType.Bit).Value = Data3;
sqlCommand.ExecuteNonQuery();
}
}
}
As noted, I stated MULTIPLE TIMES NOW, that non templated columns STILL MUST use cells collection. ONLY templated columns can and need to use FindControl. All others MUST continue to use .Cells[] collection.
It should be like this;
sqlCommand.Parameters.AddWithValue("#Item1", data1);
sqlCommand.Parameters.AddWithValue("#Item2", data2);
sqlCommand.Parameters.AddWithValue("#Item3", data3);

How can insert values into gridview rows ? ASP.NET ,C#

My question is how can i insert values into gridviews rows.Basically I have created a gridview in which i bound the footer and i want to insert values in the footer.I have create a 'textboxs','dropdownlist' and 'checkboxes'.I want when i insert value and press "Insert" button then values shown in the gridview and again i insert value and press button then show inserted values in the gridview.Here is my gridview image
and i also want to edit and delete rows as well.Here is my code :
aspx code
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
Height="104px" ShowFooter="True" Width="463px"
AutoGenerateDeleteButton="True" AutoGenerateEditButton="True">
<Columns>
<asp:TemplateField HeaderText="Column Name">
<FooterTemplate>
<asp:TextBox ID="name" runat="server"></asp:TextBox>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Data Type">
<FooterTemplate>
<asp:DropDownList ID="DropDownList2" runat="server">
</asp:DropDownList>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Allow Null">
<FooterTemplate>
<asp:CheckBox ID="allow_null" runat="server" />
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Primary Key">
<FooterTemplate>
<asp:CheckBox ID="primary" runat="server" />
</FooterTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
and here is my aspx.cs code :
protected void Button1_Click(object sender, EventArgs e)
{
string name = TextBox1.Text;
string type = DropDownList1.Text;
string allow=Null.Text;
string primary = Primary.Text;
name = ((TextBox)GridView1.FooterRow.FindControl("TextBox2")).Text;
type = ((DropDownList)GridView1.FooterRow.FindControl("DropDownList2")).Text;
allow = ((CheckBox)GridView1.FooterRow.FindControl("allow_null")).Text;
primary = ((CheckBox)GridView1.FooterRow.FindControl("primary")).Text;
}
To use the GridView in this way, with input fields in the footer and a Insert Button that is outside the GridView, you need to make a manual Insert.
I don't know how you perform an Insert using the EF model as I don't currently use it. I guess you could say the "old" way is to use an instance of SqlConnection and SqlCommand. You would use code similar to this inside your Button Click event:
// This is VB. C# is similar, you will have to convert where needed
Using connection As New SqlConnection(connectionString)
Using command As New SqlCommand(queryString, connection)
command.Connection.Open()
command.CommandType = // Typically Text or StoredProcedure as needed
command.Parameters.AddWithValue("#parameter_name1", some_value_1)
command.Parameters.AddWithValue("#parameter_name2", some_value_2)
.
.
.
command.ExecuteNonQuery()
End Using
End Using
queryString is your sql INSERT statement or a stored procedure
command.Parameters is a collection of replaceable parameter in your INSERT statement or Stored Proc.
Addendum
A Gridview is a Data bound control so typically when you use a gridview it's bound to some backing data source. If you are not using a database then you are using some other construct.
If you are using, for example, a DataTable, you would add the new rows and columns to the DataTable using its row and column methods and then rebind the DataTable to the Gridview. You don't add rows and columns directly to a GridView.
See this other SO answer by JonH for an example
In case this helps this is based on the ASPSnippets but modified to be more like you might need. Note that instead of using a DataTable I am using a List where "Row" is a class. It is somewhat a matter of personal preference which one you use. The "Row" class is:
[Serializable]
public class Row
{
public string FieldName { get; set; }
public string FieldType { get; set; }
public Boolean FieldNullible { get; set; }
public Boolean FieldPrimaryKey { get; set; }
}
My names are different from your names. Note that the ASPSnippets sample does not use TemplateFields so I am not. I am not sure if you need to make the "allow"
and/or "primary" fields Boolean so I did not process them in the form. So the ASP.Net form I have is:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
Height="104px" Width="463px"
AutoGenerateDeleteButton="True" AutoGenerateEditButton="True">
<Columns>
<asp:BoundField DataField="FieldName" HeaderText="Name" ItemStyle-Width="120" />
<asp:BoundField DataField="FieldType" HeaderText="Type" ItemStyle-Width="120" />
</Columns>
</asp:GridView>
<br /><asp:Label ID="Label1" runat="server" Text="Name:"></asp:Label>
<br /><asp:TextBox ID="txtName" runat="server" />
<br /><asp:Label ID="Label2" runat="server" Text="Type:"></asp:Label>
<br /><asp:TextBox ID="txtType" runat="server" />
<br /><asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="Insert" />
The code-behind is:
protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack)
return;
List<Row> Rows = new List<Row>();
ViewState["Rows"] = Rows;
BindGrid();
}
protected void BindGrid()
{
GridView1.DataSource = (List<Row>)ViewState["Rows"];
GridView1.DataBind();
}
protected void Insert(object sender, EventArgs e)
{
List<Row> Rows = (List < Row >)ViewState["Rows"];
Row r = new Row();
r.FieldName = txtName.Text.Trim();
r.FieldType = txtType.Text.Trim();
Rows.Add(r);
ViewState["Rows"] = Rows;
BindGrid();
txtName.Text = string.Empty;
txtType.Text = string.Empty;
}
One thing I do not like is that the GridView does not show until there is data in it. I assume you can fix that.
This does not implement the editing and deleting.

Categories

Resources