I currently have this code to populate ASP.NET gridview from code behind with DataTable.
protected void bindGridView()
{
SqlConnection sqlConn = new SqlConnection(ConfigurationManager.ConnectionStrings["connstr"].ConnectionString);
SqlCommand cmd = sqlConn.CreateCommand();
cmd.CommandText = "SELECT id AS 'Member ID', name AS Name, age AS Age, sympton AS Sympton, phone AS Phone, nirc AS NIRC, address AS Address FROM tbl_customer_profile WHERE id = #id";
cmd.Parameters.AddWithValue("#id", txtSearchID.Text);
DataTable dtSearchResult = new DataTable();
SqlDataAdapter daSearchResult = new SqlDataAdapter();
try
{
sqlConn.Open();
daSearchResult.SelectCommand = cmd;
daSearchResult.Fill(dtSearchResult);
gridSearchResult.DataSource = dtSearchResult;
gridSearchResult.DataBind();
}
catch (SqlException ex)
{
lblStatus.Text = ex.Message;
}
finally
{
sqlConn.Close();
}
}
But I would lose the Grid's Selection, Sorting, Paging functions. So I was thinking if I could fill to SqlDataSource instead of Datatable and then bind to Gridview, I wouldn't have to handle the selection, sorting etc manually?
But I can't just simply do like daSearchResult.Fill(sqlDataSource1);
Is there any workaround?
Kind of like what Neeraj was saying you can bind directly to a gridview with an SqlDataSource.
You don't need to have all that plumbing code.
This is how in asp.net
<asp:GridView ID="grid" runat="server" DataSourceID="source"></asp:GridView>
<asp:SqlDataSource ID="source" runat="server"></asp:SqlDataSource>
This is how in C#
SqlDataSource source =new SqlDataSource();
GridView grid = new GridView();
grid.DataSource = s;
grid.DataBind();
Related
I am getting this error when the gridview is created with an empty dataset. What I am trying to do is populate a dropdown list in the EmptyDataTemplate. From reading other posts the error is caused by use SqlDataReader bind gridview after SqlConnection obejct closed. However, doesn't row created fire after the gridview row is populated?
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.EmptyDataRow)
{
string connectionString3 = ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;
DropDownList ddl = (DropDownList)e.Row.FindControl("EOCEmpty");
using (SqlConnection conn3 = new SqlConnection(connectionString3))
{
SqlCommand cmd3 = new SqlCommand("SELECT DISTINCT GLAccountEOC, EOCDescription FROM Acct_GLAccount WHERE CostCenter = #CostCenter Order By EOCDescription", conn3);
cmd3.Parameters.Add("#CostCenter", System.Data.SqlDbType.Int);
cmd3.Parameters["#CostCenter"].Value = "3215";
try
{
conn3.Open();
SqlDataReader cmdreader3 = cmd3.ExecuteReader();
ddl.DataSource = cmdreader3;
ddl.DataValueField = "GLAccountEOC";
ddl.DataTextField = "EOCDescription";
ddl.DataBind();
cmdreader3.Close();
}
finally
{
conn3.Close();
}
}
}
}
The problem seem occur in these lines:
SqlDataReader cmdreader3 = cmd3.ExecuteReader();
ddl.DataSource = cmdreader3;
As you should know, ExecuteReader() method builds SqlDataReader instance (which is forward-only stream), and the connection seem to be closed when trying to access the reader. Consider using SqlDataReader.Read() method to open the reader and advances to first record, or load the contents into in-memory DataSet/DataTable and use it as GridView's data source instead.
Here is an example to load SqlDataReader contents inside DataTable:
var dt = new DataTable();
using (SqlConnection conn3 = new SqlConnection(connectionString3))
{
SqlCommand cmd3 = new SqlCommand("SELECT DISTINCT GLAccountEOC, EOCDescription FROM Acct_GLAccount WHERE CostCenter = #CostCenter Order By EOCDescription", conn3);
cmd3.Parameters.Add("#CostCenter", System.Data.SqlDbType.Int);
cmd3.Parameters["#CostCenter"].Value = "3215";
try
{
conn3.Open();
SqlDataReader cmdreader3 = cmd3.ExecuteReader();
if (cmdreader3.HasRows)
{
dt.Load(cmdreader3);
ddl.DataSource = dt; // use DataTable instead of SqlDataReader
ddl.DataValueField = "GLAccountEOC";
ddl.DataTextField = "EOCDescription";
ddl.DataBind();
}
cmdreader3.Close();
}
finally
{
conn3.Close();
}
}
If the problem still persists, use RowDataBound event handler instead of RowCreated to populate dropdownlist value (see difference between RowCreated & RowDataBound event).
Similar issue:
asp.net Invalid attempt to FieldCount when reader is closed error
After some lengthy experimentation, I discovered that having this line of code on the aspx side:
<EditItemTemplate>
<asp:DropDownList ID="ddl_Project_Owner" runat="server" Width="70px"
DataTextField="Project_Owner" DataValueField="Project_Owner"
SelectedValue='<%# Bind("Project_Owner") %>' >
</asp:DropDownList>
</EditItemTemplate>
caused an index error, but removing the SelectedValue='<%# Bind("Project_Owner") %>' piece allowed the gridview to function properly. The only thing is, when the row goes into edit mode, the dropdown is not filled with the current value. It's blank. I'd like to fill it with the current value.
On the code-behind side, I use this code to fill the dropdown:
protected void DataGrid_ResourceAllocation_EditCommand(object sender, GridViewEditEventArgs e)
{
DataGrid_ResourceAllocation.EditRowStyle.BackColor = System.Drawing.Color.LightYellow;
DataGrid_ResourceAllocation.EditIndex = e.NewEditIndex;
LoadResourceAllocationGrid();
//DataGrid_ResourceAllocation.DataBind();
SqlConnection conn = GetConnection();
int RAC = DataGrid_ResourceAllocation.Rows.Count;
GridViewRow row = DataGrid_ResourceAllocation.Rows[e.NewEditIndex];
//*********************************************************
//******** Fill in all your dropdown lists here ***********
//*********************************************************
DropDownList ddList = row.FindControl("ddl_Project_Owner") as DropDownList;
string ddListVal = ddList.SelectedValue;
//DropDownList ddList = (DropDownList)e.Row.FindControl("ddl_Project_Owner");
if (ddList != null)
{
//bind dropdown-list
string sqlStr = "Select distinct Project_Owner from tblProjectHealth order by Project_Owner";
DataSet ds = new DataSet();
conn.Open();
SqlCommand cmd = new SqlCommand(sqlStr, conn);
SqlDataAdapter ad = new SqlDataAdapter(cmd);
ad.Fill(ds);
ddList.DataSource = ds;
ddList.DataTextField = "Project_Owner";
ddList.DataValueField = "Project_Owner";
ddList.DataBind();
//DataRowView dr = e.Row.DataItem as DataRowView;
//ddList.SelectedItem.Text = dr["category_name"].ToString();
ddList.SelectedValue = ddListVal;
}
}
I tried that "ddListVal" variable because I thought it might work, but it didn't, so you can ignore that.
Can anyone help me get my dropdown to populate with the current value that exists for that field in that record?
This error is due to this : you set selectedValeue befor binding dropdownlist.
you can bind dropdownlist in RowDataBound
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddList= e.Row.FindControl("ddl_Project_Owner") as DropDownList;
if (ddList != null)
{
string sqlStr = "Select distinct Project_Owner from tblProjectHealth order by Project_Owner";
DataSet ds = new DataSet();
conn.Open();
SqlCommand cmd = new SqlCommand(sqlStr, conn);
SqlDataAdapter ad = new SqlDataAdapter(cmd);
ad.Fill(ds);
ddList.DataSource = ds;
ddList.DataTextField = "Project_Owner";
ddList.DataValueField = "Project_Owner";
ddList.DataBind();
}
}
}
The search method is here:
private void textBox1_TextChanged(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection("Data Source=DESKTOP-HNR3NJB\\mysql;Initial Catalog=stock;Integrated Security=True");
SqlDataAdapter sda = new SqlDataAdapter("SELECT ProductName FROM [stock].[dbo].[Products]", con);
sda.Fill(dt);
dataGridView1.DataSource = dt;
dt.DefaultView.RowFilter = string.Format("ProductName LIKE '%{0}%'", textBox1.Text);
}
Now that does filter out the results in the table, but it adds columns like the picture below:
Search Results
Load data function (gets called as soon as the form is loaded:
public void LoadData()
{
SqlConnection con = new SqlConnection(#"Data Source=DESKTOP-HNR3NJB\mysql;Initial Catalog=stock;Integrated Security=True");
con.Open();
//reading data from sql
SqlDataAdapter sda = new SqlDataAdapter("SELECT * FROM [stock].[dbo].[Products]", con);
dt = new DataTable();
sda.Fill(dt);
dataGridView1.Rows.Clear();
foreach (DataRow item in dt.Rows)
{
int n = dataGridView1.Rows.Add();
dataGridView1.Rows[n].Cells[0].Value = item["ProductID"].ToString();
dataGridView1.Rows[n].Cells[1].Value = item["ProductName"].ToString();
if ((bool)item["ProductStatus"])
{
dataGridView1.Rows[n].Cells[2].Value = "Active";
}
else
{
dataGridView1.Rows[n].Cells[2].Value = "Inactive";
}
dataGridView1.Rows[n].Cells[3].Value = item["Employee"].ToString();
dataGridView1.Rows[n].Cells[4].Value = item["CPU"].ToString();
dataGridView1.Rows[n].Cells[5].Value = item["RAM"].ToString();
dataGridView1.Rows[n].Cells[6].Value = item["SSD"].ToString();
dataGridView1.Rows[n].Cells[7].Value = item["HDD"].ToString();
dataGridView1.Rows[n].Cells[8].Value = item["WindowsVersion"].ToString();
dataGridView1.Rows[n].Cells[9].Value = item["Description"].ToString();
dataGridView1.Rows[n].Cells[10].Value = item["Type"].ToString();
}
con.Close();
}
Thanks
OK, so you're filling the datagridview elsewhere. You would just need to apply the rowfilter to the view to in the textbox_textchanged event
Where you're populating your current datagridview, ensure that you have your dt instantiated in a wider scope so that the textbox event can access it and then all you should have to do in your textchanged event is the following line:
dt.DefaultView.RowFilter = string.Format("ProductName LIKE '%{0}%'", textBox1.text);
This should then limit the rows to what is currently found. Here's an example of a demo database (you will have to change this to suit your needs)
DataTable dt; //declared outside a method so that multiple methods have access to it object.
private void Form1_Load(object sender, EventArgs e)
{
//Some other area where the datagridview is populated with more information
SqlConnection con = new SqlConnection(#"MyConnectionString");
con.Open();
SqlDataAdapter sda = new SqlDataAdapter("SELECT FirstName, LastName, Address, State FROM Employee", con);
dt = new DataTable();
sda.Fill(dt);
dataGridView1.DataSource = dt;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
//all that should be needed to filter the datagridview to your condition
dt.DefaultView.RowFilter = string.Format("FirstName LIKE '%{0}%'", textBox1.Text);
}
Of course, you really need to switch to using statements so that the objects used are disposed of properly but this is to show more that the basic reason your grid is doing this is that you are applying another datasource into the grid and it doesn't know that you still want all the information you had prior just limited to rows that match your filter.
EDIT - FOR CLARIFICATION
Let's do this. In your loaddata code, remark out the entire for each loop. Add the following lines
datagridview1.columns.clear();
datagridview1.datasoure = dt;
This will hide your pre-existing columns for now without you having to do it manually.
And should show the grid with all the information from the query.
Then in your textchanged event remark all your code and replace it with the line I showed above that uses the DefaultView of the datatable (dt)
That should get you up and running. Once that's done, we can make a change to the query that will allow you to show 'Active'/'InActive' instead of the checkbox for the bit field.
I have the following code LoadRegistrations(); to populate a DropDownList with values from a SQL database.
I will be likely to use this several times in different places so wanted to write a method to take care of it, instead of copying this method and changing minor details.
I've got as far as populating the DataTable but I'm not sure how to go about passing a DropDownList & the DataTextField + DataValueField into it and binding the data. Please explain what I have to do
Original Method
private void LoadRegistrations()
{
DataTable reg = new DataTable();
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnString1"].ToString()))
{
try
{
SqlDataAdapter adapter = new SqlDataAdapter("select vehicleID, regNo from dbo.Vehicles order by regNo Asc", con);
adapter.Fill(reg);
ddreg.DataSource = reg;
ddreg.DataTextField = "regNo";
ddreg.DataValueField = "vehicleID";
ddreg.DataBind();
}
catch (Exception ex)
{
// Error handling to be done
}
}
}
New Method
private DataTable PopulateDropdown(string connectionString, DataTable datatable, string query)
{
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection(connectionString))
{
try
{
SqlDataAdapter adapter = new SqlDataAdapter(query, con);
adapter.Fill(dt);
//What do I do here? I want to bind to a dropdown list passed into this method
}
catch (Exception ex) { }
}
return dt;
}
ASP to generate dropdown
<asp:DropDownList ID="ddreg" CssClass="form-control" runat="server" AppendDataBoundItems="true">
<asp:ListItem Text="<Select Registration Number>" Value="0" />
</asp:DropDownList>
You've created a method with parameters:
private DataTable PopulateDropdown(string connectionString, DataTable datatable, string query)
If you want to pass a DropDownList to that method, do exactly what you already do and add a parameter:
private DataTable PopulateDropdown(string connectionString, DataTable datatable, string query, DropDownList myDropDownList)
Then in the method you can refer to myDropDownList:
myDropDownList.DataSource = dt;
myDropDownList.DataBind();
When calling the method, you'd pass it the DropDownList you want to modify:
PopulateDropDown(someConnectionString, someDataTableYouDoNotUse, someQuery, ddreg);
private DataTable PopulateDropdown(string connectionString, DataTable datatable, string query, System.Web.UI.WebControls.DropDownList yourDropdownList)
{
SqlDataAdapter adapter = new SqlDataAdapter(query, con);
adapter.Fill(dt);
yourDropdownList.DataSource = dt;
yourDropdownList.DataBind();
return dt;
}
This is my CS file for dropdown:
protected void BindDropDownList()
{
DataTable dt = new DataTable();
string connString = System.Configuration.ConfigurationManager.AppSettings["EyeProject"];
SqlConnection conn = new SqlConnection(connString);
try
{
conn.Open();
string sqlStatement = "SELECT FirstName FROM tbl_UserDetails";
SqlCommand sqlCmd = new SqlCommand(sqlStatement, conn);
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);
sqlDa.Fill(dt);
if (dt.Rows.Count > 0)
{
DropDownList1.DataSource =dt;
DropDownList1.DataTextField = "FirstName"; // the items to be displayed in the list items
DropDownList1.DataBind();
}
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "No Data Found To display in the DropDown List";
msg += ex.Message;
throw new Exception(msg);
}
finally
{
conn.Close();
}
}
By using this one iam getting values of table Firstname values now i want to add one more item Called ALLrecords.
How can i add it.
this is my Aspx file
<div class="label">
Select Name:
<asp:DropDownList ID="DropDownList1" runat="server">
</asp:DropDownList>
</div>
Try this
DropDownList1.Items.Add(new ListItem("All Record"));
and if you want to add item with value then
DropDownList1.Items.Add(new ListItem("All Record","0"));
//or if you want to add at particular index then
DropDownList1.Items.Insert(0,new ListItem("All Record"));// 0 is index of item
hope this helps.
insert an item at specified index
DropDownListID.Items.Insert(0, new ListItem("Default text", "Default value")
DropDownList1.Items.Insert(0,new ListItem("AllRecords","itsValue_on_dropdownlist")); // use 0 to show "ALLRecords" text on top in dropdownlist
i would suggest that you should bind values to dropdownlist also.
like this -
DropDownList1.DataValueField = "FirstName";
First write onLoad with "addItems" function in dropdownlist declaring tag .aspx file like this:
then create "addItems" function in cs file.
<asp:DropDownList ID="DropDownList1" runat="server" OnLoad="addDeleteItems" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
protected void addItems(object sender, System.EventArgs e)
{
DropDownList ddl = (DropDownList)sender;
ListItem newItem = new ListItem("rose", "i");
ddl.Items.Add(newItem);
}