How to create an auto increment column and have it auto filled - c#

Here is my code:
private void AddAutoIncrementColumn(DataTable dt)
{
DataColumn column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.AutoIncrement = true;
column.AutoIncrementSeed = 0;
column.AutoIncrementStep = 1;
dt.Columns.Add(column);
}
I have an existing DataTable and want to create an auto-incremented column. That is, when i create the column i want it to automatically fill in the value 0......x. I am using the code above. But it doesn't seem to work. Any suggestions?

Try This
private void AddAutoIncrementColumn()
{
DataColumn column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.AutoIncrement = true;
column.AutoIncrementSeed = 0;
column.AutoIncrementStep = 1;
// Add the column to a new DataTable.
DataTable table = new DataTable("table");
table.Columns.Add(column);
}

There is a method on Datatable called CreateDataReader. So, clone your original datatable, add the identity column, create a datareader from the original table, then load the cloned table with the data reader. This will generate numbers in the identity column in the cloned table, then discard the original table and use the clone, eg
// original data table
DataTable origDT;
// create a reader
DataReader dr = origDT.CreatDataReader();
//clone original
DataTable clonedDT = origDT.Clone();
//add identity column
clonedDT.Columns.Add(new DataColumn(){AutoIncrement=true});
//load clone from reader, identity col will auto-populate with values
clonedDT.Load(dr);

Related

DataGridView.DataSource not working when defining columns from code

I want to define the columns of my DataGridView manually from code. Something like this:
int index = 0;
string columnName = "something";
DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn();
column.Name = columnName;
column.HeaderText = columnName;
myDataGridView.Columns.Insert(index++, column);
And then I bind the DataGridView.DataSource to a DataTable:
myDataGridView.DataSource = null;
table = new DataTable();
table = dbAccess.GetDataFromDB(); //This function returns a DataTable filled with data
myDataGridView.DataSource = table;
I already checked that after executing GetDataFromDB table is filled with data, but when binding it to DataSource, the DataGridView keeps all its row empty (although it creates as many rows as there are on the table).
Some code that I'm missing here?

How to add a progress bar to a DataGridView while loading the data 1 to 100% when complete loading

I need help with my application, everything in my application works, but I want to add one last detail that will help the user when using the application.
I have a combobox that has three selections the user will use, each selection has different warehouse database environment. so if they select in the combobox warehouse1 then will load database 1 table data to the datagridview but when they select the application is loading to show the data, so when is doing that depending how much data is sometimes takes to 5 to 15 seconds to load or more I want to add a progress bar so lets the user know to wait until the progress reaches the 100%.
So I need help on that how to make the progress bar to work while the datagridview is loading the data. if you need more information please let me know.
after the changes please check, but i am getting an error
[![enter image description here][1]][1]
//the issue I am having is the progress bar to while the datagridview is loading, the datagridview will load after the user selects the combobox selection
//the combobox event handler will fill the datagridview and the forms loads and I want while loading the progress bar to show the percentage that is loading 1 to 100%
updated code:
//global variables
//datagridview, bindingsource, data_apapter global objects variables
private DataGridView dataGridView = new DataGridView();
private BindingSource bindingSource = new BindingSource();
private SqlDataAdapter dataAdapter = new SqlDataAdapter();
//class objects
Databases lemars = new Databases();
Databases schuyler = new Databases();
Databases detroitlakeskc = new Databases();
/*
* The GetLeMarsConnectionDatabaseConnection method starts the database string connection for warehouse LeMars21St
*/
private void GetLeMarsConnectionDatabaseConnection(string selectCommand, Databases database)
{
try
{
//Create the connection string, data adapter and data table.
String connectionString = database.LeMarsConnectionString;
// Specify a connection string. Replace the given value with a
// valid connection string for a Northwind SQL Server sample
// database accessible to your system.
// Create a new data adapter based on the specified query.
dataAdapter = new SqlDataAdapter(selectCommand, connectionString);
// Create a command builder to generate SQL update, insert, and
// delete commands based on selectCommand. These are used to
// update the database.
SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter);
// Populate a new data table and bind it to the BindingSource.
System.Data.DataTable table = new System.Data.DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
dataAdapter.Fill(table);
bindingSource.DataSource = table;
// Resize the DataGridView columns to fit the newly loaded content.
dataGridView_ShowAllData.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);
}
//catch the error if cannot get a database connection
catch (SqlException)
{
MessageBox.Show("FootPrint-LEMARS Database couldn't received a connection ***ERROR***");
}
}
private void cmb_DatabaseSelection_SelectedIndexChanged(object sender, EventArgs e)
{
//Boolean selection statements to Fill the DataGridView based on the user selecction
if (cmb_DatabaseSelection.SelectedItem == "LeMars21St")
{
dataGridView_ShowAllData.DataSource = bindingSource;
//query with 11 columns
GetLeMarsConnectionDatabaseConnection("Select * from dbo.AllInvoicesInReadyStatus", lemars);
}
private void bgnWorker_LoadingForm_DoWork(object sender, DoWorkEventArgs e)
{
// TODO: query your database
// for easier reading I assume that your query-result has only one column
//string query = #"Select * from dbo.AllInvoicesInReadyStatus";
//** did you strip your sql-execution-code? have a look at https://msdn.microsoft.com/de-de/library/system.data.sqlclient.sqlcommand.aspx
var queryResult = new List<object>();
bgnWorker_LoadingForm.ReportProgress(10);
var table = new System.Data.DataTable();
// TODO: create matching columns for your query-result in the datatable
// https://msdn.microsoft.com/de-de/library/system.data.datatable.newrow(v=vs.110).aspx
// Create new DataTable and DataSource objects.
// Declare DataColumn and DataRow variables.
DataColumn column;
DataRow row;
DataView view;
// Create new DataColumn, set DataType, ColumnName, and add to DataTable.
column = new DataColumn();
column.DataType = typeof(string);
column.ColumnName = "invoice";
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = typeof(string);
column.ColumnName = "shipment";
table.Columns.Add(column);
// Create third column.
column = new DataColumn();
column.DataType = typeof(string);
column.ColumnName = "Project";
table.Columns.Add(column);
// Create fourth column.
column = new DataColumn();
column.DataType = typeof(DateTime);
column.ColumnName = "invoiceDateTB";
table.Columns.Add(column);
// Create fifth column.
column = new DataColumn();
column.DataType = typeof(DateTime);
column.ColumnName = "CreatedDate";
table.Columns.Add(column);
// Create sixth column.
column = new DataColumn();
column.DataType = typeof(string);
column.ColumnName = "typeName";
table.Columns.Add(column);
// Create seventh column.
column = new DataColumn();
column.DataType = typeof(string);
column.ColumnName = "statusName";
table.Columns.Add(column);
// Create eighth column.
column = new DataColumn();
column.DataType = typeof(decimal);
column.ColumnName = "total";
table.Columns.Add(column);
// Create ninth column.
column = new DataColumn();
column.DataType = typeof(string);
column.ColumnName = "import_status";
table.Columns.Add(column);
// Create tenth column.
column = new DataColumn();
column.DataType = typeof(DateTime);
column.ColumnName = "Time_Completed";
table.Columns.Add(column);
// Create eleventh column.
column = new DataColumn();
column.DataType = typeof(string);
column.ColumnName = "ERROR_DESCRIPTION";
table.Columns.Add(column);
for (var i = 0; i < queryResult.Count; i++)
{
var progress = 10 + (int)((float)i / queryResult.Count) * 90;
bgnWorker_LoadingForm.ReportProgress(progress);
//** dont know whats going on here
//** but normally you should iterate your data-reader here and transfer the data of your query result to the created row... like this: https://msdn.microsoft.com/de-de/library/haa3afyz(v=vs.110).aspx
row = table.NewRow();
row["invoice"].ToString();
row["shipment"].ToString();
row["Project"].ToString();
row["invoiceDateTB"] = typeof(DateTime);
row["CreatedDate"] = typeof(DateTime);
row["typeName"].ToString();
row["statusName"].ToString();
row["total"] = typeof(decimal);
row["import_status"].ToString();
row["Time_Completed"] = typeof(DateTime);
row["ERROR_DESCRIPTION"].ToString();
table.Rows.Add(row);
// TODO: add the row data to the table
// same link as before: https://msdn.microsoft.com/de-de/library/system.data.datatable.newrow(v=vs.110).aspx
}
//**begin: move this stuff to worker completed
// Create a DataView using the DataTable. .
view = new DataView(table);
//**end
// Set a DataGrid control's DataSource to the DataView.
dataGridView_ShowAllData.DataSource = view;
e.Result = table;
}
private void bgnWorker_LoadingForm_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
System.Data.DataTable table = (System.Data.DataTable)e.Result;
// TODO: Check for errors
// TODO: Assign the table to your grid
// TODO: unlock your ui, hide progress dialog
}
private void bgnWorker_LoadingForm_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// TODO: update your progress dialog/progressbar, f.e.
prgBar_DataGridViewLoading.Value = e.ProgressPercentage;
}
private void button1_Click(object sender, EventArgs e)
{
if (bgnWorker_LoadingForm.IsBusy) return;
bgnWorker_LoadingForm.RunWorkerAsync();
// TODO: lock your ui, show progress dialog or progressbar...
}
You have to do it the manual way with a BackgroundWorker (WorkerReportsProgress = true) if you want 'real'-progress...
quick-and-dirty-description:
1) In the BackgroundWorker.DoWork function query your table (f.e. 10%), create the matching DataTable locally, iterate the result and add it to a your local DataTable (10-100%).
2) Use ReportProgress to send the current progress state from inside BackgroundWorker.DoWork to your ui.
3) In BackgroundWorker.ProgressChanged you can safely update your ui/progressbar.
4) Then return (assign the value to the DoWorkEventArgs.Result) the local DataTable as a result of BackgroundWorker.DoWork...
5) and retrieve the result in BackgroundWorker.RunWorkerCompleted by accessing RunWorkerCompletedEventArgs.Result and assign the DataTable to your DataGrid
quick-and-dirty-example...
public partial class Form1 : Form
{
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// TODO: query your database
// for easier reading I assume that your query-result has only one column
var queryResult = new List<object>();
backgroundWorker1.ReportProgress(10);
var table = new DataTable();
// TODO: create matching columns for your query-result in the datatable
// https://msdn.microsoft.com/de-de/library/system.data.datatable.newrow(v=vs.110).aspx
for (var i = 0; i < queryResult.Count; i++)
{
var progress = 10 + (int)((float)i / queryResult.Count) * 90;
backgroundWorker1.ReportProgress(progress);
// TODO: add the row data to the table
// same link as before: https://msdn.microsoft.com/de-de/library/system.data.datatable.newrow(v=vs.110).aspx
}
e.Result = table;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
DataTable table = (DataTable)e.Result;
// TODO: Check for errors
// TODO: Assign the table to your grid
// TODO: unlock your ui, hide progress dialog
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// TODO: update your progress dialog/progressbar, f.e.
progressBar1.Value = e.ProgressPercentage;
}
private void button1_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy) return;
backgroundWorker1.RunWorkerAsync();
// TODO: lock your ui, show progress dialog or progressbar...
}
}
not tested, since i have a) no test-data and b) building up a full example is very time-consuming. I also might have forget something, but this could be one way to go...
Dont forget to read Alexander Petrov's link... I post a second answer instead of commenting your post to have syntax highlighting... Please remeber that i can't test your code, but i have added some comments, prefixed with a **
private void bgnWorker_LoadingForm_DoWork(object sender, DoWorkEventArgs e)
{
// TODO: query your database
// for easier reading I assume that your query-result has only one column
//string query = #"Select * from dbo.AllInvoicesInReadyStatus";
//** did you strip your sql-execution-code? have a look at https://msdn.microsoft.com/de-de/library/system.data.sqlclient.sqlcommand.aspx
var queryResult = new List<object>();
//queryResult.Add(query);
bgnWorker_LoadingForm.ReportProgress(10);
var table = new System.Data.DataTable();
// TODO: create matching columns for your query-result in the datatable
// https://msdn.microsoft.com/de-de/library/system.data.datatable.newrow(v=vs.110).aspx
// Create new DataTable and DataSource objects.
// Declare DataColumn and DataRow variables.
DataColumn column;
DataRow row;
DataView view;
// Create new DataColumn, set DataType, ColumnName, and add to DataTable.
column = new DataColumn();
//** you could write just typeof(string) here...
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "invoice";
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = Type.GetType("System.String");
column.ColumnName = "shipment";
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = Type.GetType("System.String");
column.ColumnName = "Project";
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = Type.GetType("System.DateTime");
column.ColumnName = "invoiceDateTB";
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = Type.GetType("System.DateTime");
column.ColumnName = "CreatedDate";
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = Type.GetType("System.String");
column.ColumnName = "typeName";
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = Type.GetType("System.String");
column.ColumnName = "statusName";
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = Type.GetType("System.Int32");
column.ColumnName = "total";
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = Type.GetType("System.String");
column.ColumnName = "import_status";
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = Type.GetType("System.DateTime");
column.ColumnName = "Time_Completed";
table.Columns.Add(column);
// Create second column.
column = new DataColumn();
column.DataType = Type.GetType("System.String");
column.ColumnName = "ERROR_DESCRIPTION";
table.Columns.Add(column);
for (var i = 0; i < queryResult.Count; i++)
{
var progress = 10 + (int)((float)i / queryResult.Count) * 90;
bgnWorker_LoadingForm.ReportProgress(progress);
row = table.NewRow();
//** dont know whats going on here
//** but normally you should iterate your data-reader here and transfer the data of your query result to the created row... like this: https://msdn.microsoft.com/de-de/library/haa3afyz(v=vs.110).aspx
row["invoice"] = i;
row["shipment"] = "shipment" + i.ToString();
row["Project"] = "Project" + i.ToString();
row["invoiceDateTB"].ToString();
row["CreatedDate"].ToString(); ;
row["typeName"] = "typeName" + i.ToString();
row["statusName"] = "statusName" + i.ToString();
row["total"].ToString();
row["import_status"] = "import_status" + i.ToString();
row["Time_Completed"].ToString(); ;
row["ERROR_DESCRIPTION"] = "ERROR_DESCRIPTION" + i.ToString();
table.Rows.Add(row);
// TODO: add the row data to the table
// same link as before: https://msdn.microsoft.com/de-de/library/system.data.datatable.newrow(v=vs.110).aspx
}
//**begin: move this stuff to worker completed
// Create a DataView using the DataTable.
view = new DataView(table);
// Set a DataGrid control's DataSource to the DataView.
dataGridView_ShowAllData.DataSource = view;
//**end
e.Result = table;
}

how to add a checkbox to a datagridview that is bound to a datasource?

I am new to c#. I need to have a checkbox field in the "selected" column of my datagridview instead of the "False"(or "True") text that is showing currently. This datagridview is databound and the data is obtained by reading an xml file. How can I achieve this?
before writing to the xml file, this is what i did.
DataTable dtGens = new DataTable(); //creates a new Datatable object for the Gens
dtGens.TableName = "Gen Types";
DataColumn dc1 = new DataColumn("Generator");
DataColumn dc2 = new DataColumn("alpha");
DataColumn dc3 = new DataColumn("beta");
DataColumn dc4 = new DataColumn("circuit breaker");
DataColumn dc5 = new DataColumn("description");
DataColumn dc6 = new DataColumn("Selected",System.Type.GetType("System.Boolean"));
dtGens.Columns.Add(dc1); //associates the columns to the dtGens datatable
dtGens.Columns.Add(dc2);
dtGens.Columns.Add(dc3);
dtGens.Columns.Add(dc4);
dtGens.Columns.Add(dc5);
dtGens.Columns.Add(dc6);
DataRow drow;
for (int i = 0; i < 50; i++)
{
drow = dtGens.NewRow();
drow["Generator"] = "Gen " + (i + 1).ToString();
drow["alpha"] = 0.0;
drow["beta"] = 0.0;
drow["circuit breaker"] = 0.0;
drow["description"] = "myGen";
drow["Selected"] = false;
dtGens.Rows.Add(drow);
}
//creates a new DataSet Object that will help write generator data to XML
DataSet feederProject = new DataSet();
feederProject.Tables.Add(dtGens);
feederProject.WriteXml("Generators.xml");
//preview
DataSet feederProject = new DataSet();
feederProject.ReadXml("Generators.xml");
dataGridViewLoadsDGs.DataSource = feederProject.Tables[0];
A column bound to boolean type automatically shows checkboxes. The problem is that the schema information of your DataTable is lost when it's written into the XML.
To prevent that, you can use an overload of DataSet.WriteXml that takes XmlWriteMode as a parameter, which allows you an option to write the schema information.
feederProject.WriteXml("Generators.xml", XmlWriteMode.WriteSchema);
To be able to represent a bound boolean data as a check box column you need to set AutoGenerateColumns property of the DataGridView to false. Then add columns manually and for the column that must be checkbox column set a instance of DataGridViewCheckBoxColumn:
dataGridViewLoadsDGs.AutoGenerateColumns = false;
...
dataGridViewLoadsDGs.Columns.Add(new DataGridViewCheckBoxColumn());

DataTable Decrement column value after delete row

Hi. I have a DataTable one of the column is set to AutoIncrement is true. Basically I am adding some text box values to the DataTable and then binding it to the Grid View. What I am trying to achieve is if I delete a row from the grid view the row in the DataTable is also need to be deleted and also decrement the primary key column.
DataTable is declared like this private DataTable table = new DataTable(); and code is:
DataColumn promoDetailsID = new DataColumn();
promoDetailsID.ColumnName = "promoDetailsID";
promoDetailsID.DataType = System.Type.GetType("System.Int32");
promoDetailsID.AutoIncrement = true;
promoDetailsID.AutoIncrementSeed = 1;
promoDetailsID.AutoIncrementStep = 1;
table.Columns.Add(promoDetailsID);
table.Columns.Add("StartRange", typeof(string));
table.Columns.Add("EndRange", typeof(string));
table.Columns.Add("Amount", typeof(string));
table.Columns.Add("AllocationCases", typeof(string));
table.Columns.Add("AllocationUnits", typeof(string));
if (ViewState["dtTable"] != null)
{
table = (DataTable)ViewState["dtTable"];
}
table.Rows.Add(null,TxtStartRange.Text.Trim(), TxtEndRange.Text.Trim(), TxtAllocationAmount.Text.Trim(), TxtAllocationCases.Text.Trim(), TxtAllocationUnits.Text.Trim());
grdPromotions.DataSource = table;
grdPromotions.DataBind();
ViewState["dtTable"] = table;
This is the code when I am trying to delete row from grid.
protected void grdPromotions_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
if (ViewState["dtTable"] != null)
{
table = (DataTable)ViewState["dtTable"];
int rowIndex = Convert.ToInt32(e.RowIndex);
table.Rows[e.RowIndex].Delete();
}
table.AcceptChanges();
grdPromotions.DataSource = table;
grdPromotions.DataBind();
ViewState["dtTable"] = table;
}
There is no error I am getting but the DataTable is not updating after delete.
Since you don't use a real database it makes no sense to use DataRow.Delete which just sets it's RowState to Deleted. What you want to do is to remove the row from the DataTable.
table.Rows.RemoveAt(e.RowIndex);
If you also want to decrement the primary key column, you have to make the column writable:
table.Columns[0].ReadOnly = false;
Then you need to update the value manually:
int counter = 0;
foreach(DataRow row in table.Rows)
{
row[0] = ++counter;
}
table.Columns[0].ReadOnly = true;
Side-note: don't store a DataTable in ViewState, if you need to persist it between postbacks use the Session instead. Session lives in memory whereas ViewState will be serialized and stored in the rendered html, so it will also be transferred to the client.

How to add identity column to datatable using c#

How to add identity column to datatable using c#. Im using Sql compact server.
You could try something like this maybe?
private void AddAutoIncrementColumn()
{
DataColumn column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.AutoIncrement = true;
column.AutoIncrementSeed = 1000;
column.AutoIncrementStep = 10;
// Add the column to a new DataTable.
DataTable table = new DataTable("table");
table.Columns.Add(column);
}
DataTable table = new DataTable("table");
DataColumn dc= table.Columns.Add("id", typeof(int));
dc.AutoIncrement=true;
dc.AutoIncrementSeed = 1;
dc.AutoIncrementStep = 1;
// Add the new column name in DataTable
table.Columns.Add("name",typeof(string));
table.Rows.Add(null, "A");
table.Rows.Add(null, "B");
table.Rows.Add(null, "C");
If the DataTable is already populated. you can use below method
void AddAndPopulateDataTableRowID(DataTable dt, string col, bool isGUID)
{
if(isGUID)
dt.Columns.Add(col, typeof(System.Guid));
else
dt.Columns.Add(col, typeof(System.Int32));
int rowid = 1;
foreach (DataRow dr in dt.Rows)
{
if (isGUID)
dr[col] = Guid.NewGuid();
else
dr[col] = rowid++;
}
}
You don't do autoincrement on DataTable (or front-end for that matter), unless you want to make your application a single user application only.
If you need the autoincrement, just do it in database, then retrieve the autoincremented id produced from database to your front-end.
See my answer here, just change the SqliteDataAdapter to SqlDataAdapter, SqliteConnection to SqlConnection, etc : anyway see why I get this "Concurrency Violation" in these few lines of code??? Concurrency violation: the UpdateCommand affected 0 of the expected 1 records
Just my two cents. Auto-increment is useful in a Winform app (stand alone as Michael Buen rightly said), i.e.:
DatagridView is being used to display data that does not have a "key field", the same can be used for enumeration.
I dont think its a good idea to use autoincrement on datatable if you are using insert and delete to a datatable because the number will not be rearranget, no final i will share a small idea how can we use autoincrement manual.
DataTable dt = new DataTable();
dt.Columns.Add("ID",typeof(int));
dt.Columns.Add("Produto Nome", typeof(string));
dt.Rows.Add(null, "A");
dt.Rows.Add(null, "B");
dt.Rows.Add(null, "C");
for(int i=0;i < dt.Rows.Count;i++)
{
dt.Rows[i]["ID"] = i + 1;
}
always when finalizing the insert or delete must run this loop
for(int i=0;i < dt.Rows.Count;i++)
{
dt.Rows[i]["ID"] = i + 1;
}

Categories