Data Table Copy not showing properly in GridView - c#

I have a stored procedure which actually concatenates 2 columns and returns a DataTable.
Its as below:
create procedure [dbo].[spEnqIDFyYear]
as
begin
select CONVERT(nvarchar(50),enq_id)+'/'+CONVERT(nvarchar(50),YEAR(fy_year)) as EnqIDFyYear from Sample.dbo.enquiry_details
end
GO
The output is as follows:
EnqIDFyYear
1/2015
2/2014
I have another procedure, whose output is as below:
profile_name
ProfileA
ProfileB
I bind both the procedures to 2 DataTables, merge those 2 DataTables into a 3rd one and bind the resulting DataTable to the gridview.
But the gridview is not showing as proper. It shows as below:
The rows should be aligned to each other. How to achieve it?
Code behind is as below:
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt1 = PopulateDashBoardGrid1();
DataTable dt2 = PopulateDashBoardGrid2();
DataTable dt3 = new DataTable();
dt3 = dt1.Copy();
dt3.Merge(dt2);
GridView1.DataSource = dt3;
GridView1.DataBind();
}
//Populate the main DashBoard Grid
public DataTable PopulateDashBoardGrid1()
{
using (SqlConnection con = new SqlConnection(cs))
{
SqlDataAdapter da = new SqlDataAdapter("spEnqIDFyYear", con);
DataTable dt = new DataTable();
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.Fill(dt);
return dt;
}
}
public DataTable PopulateDashBoardGrid2()
{
using (SqlConnection con = new SqlConnection(cs))
{
SqlDataAdapter da = new SqlDataAdapter("spClientProfileName", con);
DataTable dt = new DataTable();
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.Fill(dt);
return dt;
}
}
Experts please help.
Regards
Anurag

You are getting that kind of output, because Merge works in that way if the columns are not same of two datatables. So you need to write some custom code.
Here is what I have:-
static DataTable MergeDataTables(DataTable dt1, DataTable dt2)
{
DataTable dt3 = dt1.Copy();
foreach (DataColumn dc in dt2.Columns)
{
dt3.Columns.Add(dc.ColumnName).DataType = dc.DataType;
}
for (int i = 0; i < dt3.Rows.Count; i++)
{
foreach (DataColumn dc in dt2.Columns)
{
string col = dc.ColumnName;
dt3.Rows[i][col] = dt2.Rows[i][col];
}
}
return dt3;
}
You can call this method to merge both datatables.

Related

Gridview wont add another row on button click, it only adds one row and it updates that row only, how to fix this?

So I have a dropdown list that is being populate from database, the goal is to get the selected values from the dropdown list and put in the gridview. The problem is it only adds one row and only updates that row when I try to select new values from the dropdownlist.
I have tried doing Datarow row = dt.newrow() but not luck
Back End code of button click
string CS = ConfigurationManager.ConnectionStrings["POS_SystemConnectionString2"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
SqlCommand cmd = new SqlCommand("SELECT * FROM Product_Details WHERE Model = '" + ddlModel.SelectedItem.Text + "' AND Price = '" +ddlPrice.SelectedItem.Text + "'", con);
con.Open();
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
First image when I select values from dropdown list for first time
Second image is when I select new values from dropdown list but it updates previous table and does not add new row in gridview
On Add Button click you are retrieving new data from database and creating new datatable that's why you are loosing the previously selected data.
You need to maintain the previously retrieved data between two clicks on Add button.
You need to create a separate DataTable in aspx.cs and store it in the ViewState and add new row to that table on button click and re-bind it to the GridView.
You need to write following code to achieve this.
//This method will check if the table exist in the ViewState
//If table does not exist in ViewState, a new table will be created and stored in ViewState
private DataTable GetDataTable()
{
DataTable dt = ViewState["SelectedModels"] as DataTable;
if (dt == null)
{
dt = new DataTable();
dt.TableName = "ColorData";
dt.Columns.Add(new DataColumn("Model", typeof(string)));
dt.Columns.Add(new DataColumn("Price", typeof(string)));
ViewState["SelectedModels"] = dt;
}
return dt;
}
//This method will store DataTable to ViewState
private void SaveDataTable(DataTable dataTable)
{
ViewState["SelectedModels"] = dataTable;
}
//This method will get the data from the database, add it to the DataTable
//And it will re-bind the DataTable to the GridView and store the updated DataTable to ViewState
private void AddItemToList(string modelName, string price)
{
string CS = ConfigurationManager.ConnectionStrings["POS_SystemConnectionString2"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
using (SqlCommand cmd =
new SqlCommand("SELECT * FROM Product_Details WHERE Model = #modelName AND Price = #price", con))
{
var modelParameter = new SqlParameter();
modelParameter.ParameterName = "#modelName";
modelParameter.Value = modelName;
cmd.Parameters.Add(modelParameter);
var priceParameter = new SqlParameter();
priceParameter.ParameterName = "#price";
priceParameter.Value = price;
cmd.Parameters.Add(priceParameter);
con.Open();
using (var sqlReader = cmd.ExecuteReader())
{
var dataTable = GetDataTable();
while (sqlReader.Read())
{
var dataRow = dataTable.NewRow();
//Hear I assume that Product_Details table has Model and Price columns
//So that sqlReader["Model"] and sqlReader["Price"] will not have any issue.
dataRow["Model"] = sqlReader["Model"];
dataRow["Price"] = sqlReader["Price"];
dataTable.Rows.Add(dataRow);
}
SaveDataTable(dataTable);
GridView1.DataSource = dataTable;
GridView1.DataBind();
}
}
}
}
And now the Click Event Handler of the button should call the above method as following.
protected void bttnAdd_Click(object sender, EventArgs e)
{
AddItemToList(ddlModel.SelectedItem.Text, ddlPrice.SelectedItem.Text);
}
This should help you resolve your issue.

how to fill (write) datacolumn to list<>?

I am trying to get a datacolumn with values (already filled in data table) and write it in an auto property present in access layer. Currently, the method i am using is fetching data from sql and passing the values to gird. I am trying to use that method and already filled datatable but the problem is, auto property is only reading column name and as a result i am getting column name in another control (list box). The below is my method in BLL.
DAL d = new DAL();
public Object getfeechallan(Bal B)
{
sqlcommand cmd = new sqlcommand("select * from tblfee where fee_challan_No like #abc,d.con");
cmd.parameters.addwithvalue("#abc","%"+b.fee_challan_No+"%");
datatable dt=d.getdatafilter(cmd);
foreach(datacolumn dd in dt.columns)
{
if(dd.columnname=="ftid")
{
list<DataColumn> dc = new list<DataColumn>();
dc.Add(dd);
b.abc=dc;
}
} return dt;
}
My method in DAL is
public Datatable getdatafilter(SqlCommand CMD)
{
SqlDataAdapter da = new SqlDataAdapter(CMD);
Datatable dt = new Datatable ();
da.Fill(dt);
return dt;
}
Auto Property is
public list<DataColumn> abc {get; set;}
Ok.. so the below should do it.
public DataTable getfeechallan(Bal b)
{
SqlDataAdapter sdb = new SqlDataAdapter("Select count(*) From reserve", con);
DataTable dt = new DataTable();
List<string> dc = new List<string>();
sdb.Fill(dt);
foreach (DataRow dd in dt.Rows)
{
dc.Add(dd["ftid"].ToString());
}
Bal.abc = dc;
return dt;
}
One other observation. Unless you need the datatable returning, change the return type to "void". I presume all the data you need is now in the "Bal" object.
if you are trying to get a list contains all values in certain column
you can not just ref the column
you need to loop all rows of that column
List<object> values = new List<object>();
for(int i = 0; i < dt.Rows.Count(); i++)
{
values.Add(dt[i]["columnName"]);
}

Inserting data into gridView without using SqlDataSource and DataBind from a Sql Table

In my database web application, I am trying to add data to a column in gridView from a SQL table using the following code snippet
public void GetRowHeaders(GridView gridViewSample)
{
string commandstr = #"SELECT ID FROM WhiteBoardTest WHERE ID!=0 ORDER BY ID";
SqlCommand rowHeaderCmd = new SqlCommand(commandstr, sqlcon);
sqlcon.Open();
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = rowHeaderCmd;
da.Fill(dt);
for (int i = 0; i < dt.Columns.Count; i++)
{
for (int j = 0; j < dt.Rows.Count; j++)
{
gridViewSample.Rows[0].Cells[j].Text = dt.Rows[j][i].ToString();
}
}
sqlcon.Close();
}
When I ran the above code, I got the error saying
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection
I understand that the exception has occurred because the gridView has no rows or columns available.
Can anyone suggest me how to add rows to a column and also I am not using SqlDataSource because I would like add one more column to the gridView from a different table.
I would just include the extra column in your select statement and just bind to the gridview - unless there's a specific reason for not doing that. note the new sql!
public void GetRowHeaders(GridView gridViewSample)
{
string commandstr = #"SELECT a.*, b.somecolumn FROM tablea as a inner join tableb as b on b.someid= a.someid WHERE ID!=0 ORDER BY ID";
SqlCommand rowHeaderCmd = new SqlCommand(commandstr, sqlcon);
sqlcon.Open();
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = rowHeaderCmd;
da.Fill(dt);
gridViewSample.DataSource = dt;
gridviewSample.DataBind();
sqlcon.Close();
}
Or you could populate a collection of some class ( remember to use properties for gridviews databind), a List maybe, and just databind that to the grid.
Dayakar, what you can do is add additional column and data to DataTable itself and then bind it to the gridview. below is a example code.
private void SetupGridView()
{
var dt = GetDataTable();
// add addition column
dt.Columns.Add(new DataColumn() {ColumnName = "Id2", DataType = typeof (int)});
// add additional data
for (var i = 0; i < dt.Rows.Count; i++)
{
dt.Rows[i]["Id2"] = Convert.ToInt32(dt.Rows[i][0])*2;
}
GridView1.DataSource = dt;
GridView1.DataBind();
}
You can also merge two datatables to create one datatable and then bind it to gridview. Refer http://msdn.microsoft.com/en-us/library/fk68ew7b.aspx

how to store multiple datatable into a single dataset

I have multiple datatable. I want to show all the datatable rows into a single gridview.
How can I do that?
DataTable dtbag101 = (DataTable)Session["bag101"];
DataTable dtwallet111 = (DataTable)Session["wallet111"];
DataSet ds= new DataSet();
ds.Tables.Add(dtbag101);
ds.Tables.Add(dtwallet111);
GridView1.DataSource= ds;
GridView1.DataBind();
The column names for both datatable are the same.
Here I was trying to use dataset but only first DataTable i.e. datbag101 was showing in the gridview.
How can I show all the values in one gridview?
Provided that your two data tables have the same columns, you can UNION them with some handy LINQ.
DataTable dtbag101 = (DataTable)Session["bag101"];
DataTable dtwallet111 = (DataTable)Session["wallet111"];
var result = dtbag101.AsEnumerable().Union(dtwallet111.AsEnumerable());
GridView1.DataSource = result;
GridView1.DataBind();
Otherwise try use DataTable.Merge:
DataTable dtbag101 = (DataTable)Session["bag101"];
DataTable dtwallet111 = (DataTable)Session["wallet111"];
dtbag101.Merge(dtwallet111, true);
GridView1.DataSource = dtbag101;
GridView1.DataBind();
I'm not sure why this isn't working for you. Try this method (grabbed from here):
public static DataTable Union(DataTable First, DataTable Second)
{
//Result table
DataTable table = new DataTable("Union");
//Build new columns
DataColumn[] newcolumns = new DataColumn[First.Columns.Count];
for(int i=0; i < First.Columns.Count; i++)
{
newcolumns[i] = new DataColumn(
First.Columns[i].ColumnName, First.Columns[i].DataType);
}
table.Columns.AddRange(newcolumns);
table.BeginLoadData();
foreach(DataRow row in First.Rows)
{
table.LoadDataRow(row.ItemArray,true);
}
foreach(DataRow row in Second.Rows)
{
table.LoadDataRow(row.ItemArray,true);
}
table.EndLoadData();
return table;
}
Call the method with your two datatables:
GridView1.DataSource = Union(dtbag101, dtwallet111);
You can simply use DataTable.Merge method
DataTable dtbag101 = (DataTable)Session["bag101"];
DataTable dtwallet111 = (DataTable)Session["wallet111"];
dtbag101.Merge(dtwallet111); //Merge action
GridView1.DataSource= dtbag101;
GridView1.DataBind();
I dont know much about this. Just referred it now.
or else
try for loop
DataSet ds = new DataSet();
addTables(dtbag101);
addTables(dtwallet111); //ds will be merge of both tables here
private void addTables(DataTable dt)
{
for(int intCount = ds.Tables[0].Rows.Count; intCount < dt.Rows.Count;intCount++)
{
for(int intSubCount = 0;intSubCount < dt.Columns.Count; intSubCount++)
{
ds.Tables[0].Rows[intCount][intSubCount] = dt.Rows[intCount][intSubCount];
}
}
}
You may need to use DataTable.Merge
DataTable dtAll = new DataTable();
dtAll = dtbag101 .Copy();
dtAll.Merge(dtwallet111, true);
GridView1.DataSource= dtAll;
GridView1.DataBind();
Edit to show how it should work
private void BindGridWithMergeTables()
{
DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
dt1.Columns.Add("ID");
dt2.Columns.Add("ID");
DataRow dr1 = dt1.NewRow();
DataRow dr2 = dt2.NewRow();
dr1["ID"] = "1";
dr2["ID"] = "2";
dt1.Rows.Add(dr1);
dt2.Rows.Add(dr2);
DataTable dtAll = new DataTable();
dtAll = dt1.Copy();
dtAll.Merge(dt2, true);
dataGridView1.DataSource = dtAll;
dataGridView1.DataBind();
}

Inserting records from datatable into list

I am using datatable to retrieve 1000 records from mysql database. I want to copy each record as it is to list. But I do not know the exact syntax for that.
Here is the following code I am trying to retrieve:
cmdmysql.CommandText = "select * from marctest.spectrum";
conn.Open();
MySqlDataAdapter da = new MySqlDataAdapter(cmdmysql.CommandText, conn);
//MySqlDataReader reader;
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
dataGridView1.DataMember = dt.TableName;
// row = dataGridView1.DataSource.ToString();
//row = dt.TableName;
MySqlDataReader reader;
reader = cmdmysql.ExecuteReader();
List<string> mylist = new List<string>();
foreach(DataRow row1 in dt.Rows)
{
mylist.Add(dt.Rows.ToString());
}
textBox1.Text = mylist.ToString();
Does anybody have an idea regarding the same? This is my actual code...
I'm not sure that doing DataRow.ToString() is going to get you anything useful (most likely just the object type).
If you want the data from each row as a string (perhaps tab-delimited?), you can try:
foreach(DataRow row1 in dt.Rows) {
StringBuilder sb = new StringBuilder();
foreach(DataColumn col in dt.Columns) {
sb.Append(row1[col].ToString();
sb.Append('\t');
}
mylist.Add(sb.ToString());
}
This will croak, if any of your column's have a null value so you may want to handle that.
Assuming that dt is the query result, and If you only need to convert these results to strings, then this should work:
foreach(DataRow row1 in dt.Rows)
mylist.Add(row1.ToString();

Categories

Resources