I have a table having 2 columns viz ID and DETAILS.Data in a table is like
id=01 details="pritam=123 sourav=263" like this
i am working on a windows for application ..when the application will run the output comes what i am going to tell.. 1.in my application one combobox is there.when the application will run all the id will be bind in a combobox from the table. 2.when user will choose any id suddenly the details column data will be shown in a datagrid view in a splitted format like this.
NAME KEY
PRITAM 123
SOURAV 263
in this data grid view user can delete ant row by selecting the and click on the below delete button. insert any row by clickng the add new row button at the end ,modify any existing data and finally click on the update button and all the data are going to be stored in that data base like in previous format.. for that i have written the code in c# like this..
namespace windows_csharpp
{
public partial class Form5 : Form
{
SqlConnection cc = new SqlConnection("Integrated Security=true;database=EDIXfer");
SqlDataAdapter da;
DataTable dt;
public Form5()
{
InitializeComponent();
}
private void Form5_Load(object sender, EventArgs e)
{
string sql="select EDIScheduleID from ETAProcessSchedule";
da= new SqlDataAdapter(sql, cc);
dt = new System.Data.DataTable();
da.Fill(dt);
for (int x = 0; x < dt.Rows.Count; x++)
{
comboBox1.Items.Add(dt.Rows[x][0].ToString());
}
}
ArrayList ls = new ArrayList();
int ss = 0;
int ss1 = 0;
int ssp = 1;
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string sql = "select * from ETAProcessSchedule where EDIScheduleID='" + comboBox1.SelectedItem.ToString() + "'";
SqlDataAdapter adp = new SqlDataAdapter(sql, cc);
DataTable dt = new System.Data.DataTable();
adp.Fill(dt);
string stp = dt.Rows[0][21].ToString();
string[] stp1 = stp.Split(' ');
List<Class1> lst = new List<Class1>();
ls.Clear();
for (int x = 0; x < stp1.Length; x++)
{
ls.Add(stp1[x].ToString());
}
for (int x = 0; x < ls.Count; x++)
{
string ssttt = ls[x].ToString();
string[] sssp = ssttt.Split('=');
for (int x1 = 1; x1 < sssp.Length; x1++)
{
ss = 0;
ss1 = ssp;
Class1 cs = new Class1()
{
Value = sssp[ss], Key= sssp[x1].ToString()
};
lst.Add(cs);
}
}
dataGridView1.DataSource = lst;
}
private void Update_Click(object sender, EventArgs e)
{
string value = null;
string keys = null;
string query = null;
string str = null;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
value = dataGridView1.Rows[i].Cells[0].Value.ToString();
keys = dataGridView1.Rows[i].Cells[1].Value.ToString();
string ss = value + '=' + keys;
str += ss + ' ';
}
query = "update ETAProcessSchedule set ProcParameters='"+str+"' where EDIScheduleID='"+comboBox1.SelectedItem.ToString()+"'";
da = new SqlDataAdapter(query, cc);
dt = new DataTable();
da.Fill(dt);
MessageBox.Show("Data Updated In Database Successfully");
}
and one class file is also there ..
class Class1
{
public string Value { get; set; }
public string Key { get; set; }
}
kindly help me in delete the selected row ,add the new row and update the all data in database like in previous format..
I think you already have working approach. If I understand right you need only two functions:
- Load Schedule details in the DataGridView (one key-value pair per row)
- Save edited/added/deleted key-value pairs to the database
Be sure next properties of DataGridView set to true:
this.YourDataGridView.AllowUserToAddRows = true;
this.YourDataGridView.AllowUserToDeleteRows = true;
And of course columns must be editable
In the methods was used const variables which was created in your Form (Form1)
private const string DETAILSDELIMITER = ' ';
private const string NAMEKEYDELIMITER = '=';
Method for loading schedule details in the DataGridView
//Use SqlParameters in the query,
//if not your application vulnerable for sql injection
private void LoadScheduleDetails(string scheduleID)
{
//You working only with one column, do not use '*' in SELECT statement if not nessesary
string query = "SELECT EDIScheduleID, ProcParameters FROM ETAProcessSchedule WHERE EDIScheduleID = #ScheduleID";
DataTable details = new DataTable();
//Get data from database
using (SqlConnection yourConnection = new SqlConnection(_YourConnectionString))
{
using(SqlCommand detailsCommand = new SqlCommand(query, yourConnection))
{
//Adding parameter
SqlParameter id = new SqlParameter { ParameterName = "#ScheduleID", SqlDbType = SqlDbType.NVarChar, Value = scheduleID };
detailsCommand.Parameters.Add(id);
using (SqlDataAdapter yourAdapter = new SqlDataAdapter(detailsCommand ))
{
yourAdapter.Fill(details);
}
}
}
this.YourDataGridView.Rows.Clear();
if (details.Rows.Count > 0)
{
DataRow temp = details.Rows[0];
//get column by name.
string[] pairs = temp.Field<String>("ProcParameters").Split(Form1.DETAILSDELIMITER);
//Adding rows manually without DataSource
foreach(string pair in pairs)
{
this.YourDataGridView.Rows.Add(pair.Split(Form1.NAMEKEYDELIMITER));
}
}
}
Method for saving data
I think better if you create columns already in the designer
Then you can access columns by it's name without hardcoding indexes
private void SaveDetails(string scheduleID)
{
StringBuilder details = new StringBuilder();
foreach(DataGridViewRow dgvr in this.YourDataGridView.Rows)
{
string name = dgvr.Cells[this.dgvColumn_Name.Name].Value.ToString();
string key = dgvr.Cells[this.dgvColumn_Key.Name].Value.ToString();
//Here you can check if values are ok(not empty or something else)
//Create pair
details.Append(Form1.DETAILSDELIMITER);
details.Append(name);
details.Append(Form1.NAMEKEYDELIMITER);
details.Append(key);
}
//remove first space character
if (details.Length > 0)
details.Remove(0, 1);
//Save data to database
string query = "UPDATE ETAProcessSchedule SET ProcParameters=#Details WHERE EDIScheduleID=#ScheduleID";
using (SqlConnection yourConnection = new SqlConnection(_YourConnectionString))
{
using (SqlCommand saveCommand = new SqlCommand(query, yourConnection))
{
//Adding parameters
SqlParameter id = new SqlParameter { ParameterName = "#ScheduleID", SqlDbType = SqlDbType.NVarChar, Value = scheduleID };
SqlParameter procParams = new SqlParameter { ParameterName = "#Details", SqlDbType = SqlDbType.NVarChar, Value = details.ToString() };
saveCommand.Parameters.Add(id);
saveCommand.Parameters.Add(procParams);
saveCommand.ExecuteNonQuery();
MessageBox.Show("Data Updated In Database Successfully");
}
}
}
Then use LoadScheduleDetails in the comboBox1_SelectedIndexChanged eventhandler
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string scheduleID = comboBox1.SelectedItem.ToString();
if(String.IsNullOrEmpty(scheduleID) == false)
{
this.LoadScheduleDetails(scheduleID);
}
}
After data loaded, user can change it, add rows, delete rows
When user pressed "Update" button then use SaveDetails method,
where we collect data from all rows and update database with it
private void Update_Click(object sender, EventArgs e)
{
string scheduleID = comboBox1.SelectedItem.ToString();
if(String.IsNullOrEmpty(scheduleID) == false)
{
this.SaveDetails(scheduleID);
}
}
On your form load bind data:-
EDIT : -
private void Form5_Load(object sender, EventArgs e)
{
comboBox1.DataSource = loadddltable();
comboBox1.DisplayMember = "Name";
comboBox1.ValueMember = "ID";
}
public DataTable loadddl()
{
OleDbDataReader obj = null;
DataTable dt = new DataTable();
try
{
obj_dbconnection.CommandText = "Select * from TableName";
obj = obj_dbconnection.ExecuteReader();
if (obj != null)
{
if (obj.HasRows)
{
dt.Load(obj);
}
}
}
catch (Exception)
{
}
finally
{
if (obj != null)
{
obj.Close();
obj_dbconnection.Close();
}
}
return dt;
}
/*Code for Execute Reader*/
public OleDbDataReader ExecuteReader()
{
OleDbDataReader dr = null;
try
{
Open();
dr = cmd.ExecuteReader();
}
catch(Exception)
{ }
return dr;
}
/*Code for binding grid data*/
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
dataGridView1.DataSource= getDataForSelectedId(comboBox1.SelectedValue);
}
And then insert,edit,delete buttons as template fields to dataGridView and use dataGridView1_CellClick event to insert edit delete
Related
This is the data pass from form 1 when the from3 button click:
string DataT1, Table2, T3;
DataTable DT5,DT;
public Form3(DataTable DT4,string DT1, string T2,string T31)
{
DataT1 = DT1;
Table2 = T2;
T3 = T31;
DT5 = DT4;
InitializeComponent();
loaddata();
}
The textbox fill automatically when the datagridview is fill with data
private void FillData(DataTable DataT)
{
TextBox TB1;
int y = 12;
foreach (DataColumn DC in DataT.Columns)
{
TB1 = TB(0, y);
TB1.DataBindings.Add(new Binding("Text".ToString(), DataT, DC.ColumnName));
panel1.Controls.Add(TB1);
y += 23;
}
}
//the textbox object
private TextBox TB(int x,int y)
{
TextBox TB1 = new TextBox
{
Text = "",
Size = new Size(150,50),
Location=new Point(x,y)
};
return TB1;
}
Below is the code that I want to add the textbox data or value to SQL Server when the button save is clicked:
private void loaddata()
{
DataTable DT1 = new DataTable();
SqlConnection SC = new SqlConnection(DataT1);
SqlDataAdapter SDA = new SqlDataAdapter(Table2, SC);
SqlCommandBuilder SCB = new SqlCommandBuilder(SDA);
SDA.Fill(DT1);
DT = DT1;
dataGridView1.DataSource = DT;
//the code to save and update data on textbox
FillData((DataTable)dataGridView1.DataSource);
}
private void button1_Click(object sender, EventArgs e)
{
int j = 0;
string[] Text = null;
foreach (TextBox TB in panel1.Controls)
{
j++;
Text[j].Insert(j, TB.Text.ToString());//this way i create a string[] to save each textbox value
}
/*how the code to save programmatically added textbox value to sql
* database follow by each textbox to each columns in database
* table and another sql command to insert new record*/
}
This is the form1 SQL Server connection string
//this is the form one, the database and table is choose by combobox and fill it to datagridview
string T1, T2, T3;
DataTable Data2;
private void LoadData()
{
T1 = "Server=localhost;Initial Catalog=" + comboBox2.SelectedItem + ";Integrated Security=SSPI;";
T2 = "Select * from " + comboBox3.SelectedItem;
T3 = comboBox3.SelectedItem.ToString();
SqlConnection SCConnect = new SqlConnection(T1);
SCConnect.Open();
StringBuilder SBBuilder = new StringBuilder(T2);
SqlDataAdapter SDA = new SqlDataAdapter(SBBuilder.ToString(),SCConnect);
SqlCommandBuilder SCB = new SqlCommandBuilder(SDA);
DataTable DT = new DataTable();
SDA.Fill(DT);
dataGridView1.DataSource = DT;
Data2 = DT;
filltexttotextbox((DataTable)dataGridView1.DataSource);
}
When the button click it will open and pass data to form3:
private void button1_Click(object sender, EventArgs e)
{
Form3 F3 = new Form3(Data2, T1, T2,T3);
F3.ShowDialog();
}
to add new record to database
enter image description here
to update record to database
enter image description here
I found the best way to handle the changes that don't to fire the changes event basically.
Just save the loaded as OriginDataTable and use EditorDataTable as a editor.
For quickly implementation. I will use DataGridView as a editor directly without passing to panel1 on your code.
DataTable OriginalDataTable = new DataTable();
DataTable EditorDataTable = new DataTable();
public MainForm()
{
InitializeComponent();
EditorDataTable.Columns.Add("Col1");
EditorDataTable.Columns.Add("Col2");
EditorDataTable.Columns.Add("Col3");
EditorDataTable.Rows.Add("my-col-1-row-1", "my-col-2-row-1", "my-col-3-row-1");
EditorDataTable.Rows.Add("my-col-1-row-2", "my-col-2-row-2", "my-col-3-row-2");
EditorDataTable.Rows.Add("my-col-1-row-3", "my-col-2-row-3", "my-col-3-row-3");
dataGridView.DataSource = EditorDataTable;
OriginalDataTable = EditorDataTable.Copy(); // Save loaded datatable
}
Then I would use the comparison between origin and editor
private IEnumerable<DataRow> ListOutDataRowChanged(DataTable originDt, DataTable changeDt)
{
for (int i = 0; i < originDt.Rows.Count; i++)
{
if (string.Join(";",originDt.Rows[i].ItemArray) != string.Join(";", changeDt.Rows[i].ItemArray))
yield return originDt.Rows[i];
}
}
The save button would be
private void btnSave_Click(object sender, EventArgs e)
{
var list = ListOutDataRowChanged(OriginalDataTable, EditorDataTable);
MessageBox.Show("List changes count: " + list.Count());
// Insert this list to SQL here
}
The benefit of this implementation is:
We could handle when we are gonna send to SQL
Edited then restore back wouldn't count as changes
No need to trigger fire event
Rollback
My program is supposed to take team names from an XML file and display them in the listbox, and when a team is selected from the listbox, players with a higher batting average on the team are displayed in a datagridview. For some reason nothing is showing up in my listbox, and therefore I cannot select anything and test if my program works.
public partial class Form1 : Form
{
DataSet resultset = new DataSet();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
resultset.ReadXml("Baseball.xml");
var myQuery = resultset.Tables[0].AsEnumerable().Select(row => new
{
teamname = row.Field<string>("Team")
})
.Distinct();
foreach (var rowname in myQuery)
{
listBox1.Items.Add(rowname.teamname.ToString());
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
double TotalhitsAverage, TotalatBatAverage, TeamAverage;
DataTable playerInformation = new DataTable();
DataRow[] tableName = resultset.Tables[0].Select("Team = '" + listBox1.SelectedItem + "'");
playerInformation = tableName.CopyToDataTable();
DataTable clonedcolumns = playerInformation.Clone();
clonedcolumns.Columns[3].DataType = typeof(double);
clonedcolumns.Columns[2].DataType = typeof(double);
foreach (DataRow row in playerInformation.Rows)
{
clonedcolumns.ImportRow(row);
}
TotalhitsAverage = clonedcolumns.AsEnumerable().Average(r => r.Field<double>("hits"));
TotalatBatAverage = clonedcolumns.AsEnumerable().Average(r => r.Field<double>("atBats"));
TeamAverage = TotalhitsAverage / TotalatBatAverage;
DataTable playerAverage = new DataTable();
DataRow rowPlayer = playerAverage.NewRow();
playerAverage.Columns.Add("Player", typeof(String));
playerAverage.Columns.Add("Batting Avg", typeof(double));
for (int i = 0; i < clonedcolumns.Rows.Count; i++)
{
double averageplayer = Convert.ToDouble(clonedcolumns.Rows[i][3]) / Convert.ToDouble(clonedcolumns.Rows[i][2]);
if (TeamAverage <= averageplayer)
{
playerAverage.Rows.Add(clonedcolumns.Rows[i][0].ToString(), Math.Round(averageplayer, 4));
}
}
DataView view = playerAverage.DefaultView;
view.Sort = "Batting Avg DESC";
DataTable sortedDate = view.ToTable();
dgvBaseball.DataSource = sortedDate;
dgvBaseball.AutoSize = true;
}
}
I have a DataGridView on WindowsForm where I'm passing data from my database. The purpose of this DataGridView is to enable to user to click on a value and modify it. However, I don't want the user to leave the value blank, add words, only numbers.. and of course not change the Id, which is the primary key of my table.
I'm trying to achieve this by disabling the column which host the id of the table, however I don't know how to tell that column to disable editing.
Here is my code:
public partial class eraseGrade : Form
{
Conexion con;
String rut;
DataTable dt;
SqlDataAdapter sda;
SqlCommandBuilder scb;
public eraseGrade()
{
InitializeComponent();
cbxAsig.Enabled = false;
cbxAsig.Enabled = false;
btnNotas.Enabled = false;
btnBorra.Enabled = false;
}
private void btnBuscar_Click_1(object sender, EventArgs e)
{
Conexion con = Conexion.saberEstado();
rut = txtRut.Text.Trim();
if (validarTXTVacios(txtRut))
{
MessageBox.Show("Add a Rut, please");
}
else
{
Alumno a = new Alumno(rut);
a.buscar(a);
cbxAsig.Items.Clear();
if (a.Nombre != null)
{
lblNombre.Text = a.Nombre + " " + a.Apellido;
cbxAsig.Enabled = true;
AsignaturaAlumno b = new AsignaturaAlumno();
List<AsignaturaAlumno> l = b.buscarTodosByAlumno(rut);
List<String> codigosAsig = new List<string>();
if (l.Count != 0)
{
for (int i = 0; i < l.Count(); i++)
{
codigosAsig.Add(l.ElementAt(i).Cod_asig.ToString());
}
Asignatura asigT = new Asignatura();
List<Asignatura> asig = new List<Asignatura>();
for (int i = 0; i < codigosAsig.Count(); i++)
{
asig.Add(asigT.buscarbyCod(codigosAsig.ElementAt(i).ToString()));
}
for (int i = 0; i < asig.Count(); i++)
{
cbxAsig.Items.Add(asig.ElementAt(i).CodAsignatura);
}
cbxAsig.Enabled = true;
btnNotas.Enabled = true;
}
}
else
{
lblNombre.Text = "";
MessageBox.Show("Alumno no encontrado");
lblAsig.Text = "";
cbxAsig.Enabled = false;
btnNotas.Enabled = false;
btnBorra.Enabled = false;
}
}
}
private void cbxAsig_SelectedIndexChanged(object sender, EventArgs e)
{
Conexion con = Conexion.saberEstado();
Asignatura asignatura = new Asignatura();
Asignatura l = asignatura.buscarbyCod(cbxAsig.SelectedItem.ToString());
lblAsig.Text = l.Nombre + " (" + l.IdSeccion + ")";
}
Here is the code that obtains data from the database and inserts it into the DataGridView.
private void btnNotas_Click(object sender, EventArgs e)
{
Conexion con = Conexion.saberEstado();
if (cbxAsig.SelectedItem != null)
{
String codigo = cbxAsig.SelectedItem.ToString();
sda = new SqlDataAdapter(#"SELECT id, num_eval AS Evaluacion, porcentaje AS Porcentaje, nota AS Nota FROM registro WHERE rut = #rut AND cod_asig = #cod_asig", con.Con);
sda.SelectCommand.Parameters.AddWithValue("#rut", rut);
sda.SelectCommand.Parameters.AddWithValue("#cod_asig", codigo);
dt = new DataTable();
sda.Fill(dt);
dataGridView1.DataSource = dt;
btnBorra.Enabled = true;
}
else
{
MessageBox.Show("Seleccione una asignatura");
}
}
public Boolean validarTXTVacios(TextBox r)
{
if (txtRut.Text.Equals(""))
{
return true;
}
return false;
}
Here is the button that updates the table with the new data from the columns. It doesn't respect primary keys or data types.
private void btnBorra_Click(object sender, EventArgs e)
{
scb = new SqlCommandBuilder(sda);
sda.Update(dt);
}
}
}
Just set that column's ReadOnly to true like this:
dataGridView1.Columns[0].ReadOnly = true;
You should change 0 to the id's column index.
EDIT: To validate a column to be for example int you could do like this:
dataGridView1.Columns[0].ReadOnly = true;
dataGridView1.AllowUserToAddRows = false;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
int x;
if (int.TryParse(row.Cells[1].Value.ToString(), out x))
{
MessageBox.Show("Valid");
}
}
You can achieve this by setting Row.Cells[cellIndex].Enabled = false; during GridView RowDataBound event.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Cells[cellIndex].Enabled = false;
}
}
Alter cellIndex to your actual id cell index.
I'm new to Asp.net and I'm trying to figure out how to update a value in a SqlDataSource programmatically. Here's my button click listener:
protected void ApproveLoanButton_Click(object sender, EventArgs e)
{
DataView dv = (DataView)DetailsSqlDataSource.Select(DataSourceSelectArguments.Empty);
dv.AllowEdit = true;
using (var dt = dv.ToTable())
{
var oldValue = dt.Rows[0]["IsApproved"].ToString();
dt.Rows[0]["IsApproved"] = true;
var newValue = dt.Rows[0]["IsApproved"].ToString();
dt.AcceptChanges();
GridView1.DataBind();
DetailsView1.DataBind();
}
}
The oldValue is false and the newValue is true so I am changing the value but it doesn't save to the database when I call AcceptChanges(). What am I doing wrong here? I've already spent hours on this. Thanks for your help!
I do not have what your DetailsSqlDataSource is, or what your database structure is like, but you would obviously need to write a few Save and Read methods.
If you did that, you would have something like this:
protected void ApproveLoanButton_Click(object sender, EventArgs e)
{
DataView dv = (DataView)DetailsSqlDataSource.Select(DataSourceSelectArguments.Empty);
dv.AllowEdit = true;
using (var dt = dv.ToTable())
{
var oldValue = dt.Rows[0]["IsApproved"].ToString();
if (-1 < SaveApproved((int)dt.Rows[0]["ID"], true))
{
dt.Rows[0]["IsApproved"] = true;
var newValue = dt.Rows[0]["IsApproved"].ToString();
dt.AcceptChanges();
DetailsSqlDataSource = GetTable();
GridView1.DataBind();
DetailsView1.DataBind();
}
}
}
You will need to modify these to work, but here is a sample:
private const string SQL_CONNECTION = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;";
private DataTable GetTable()
{
var table = new DataTable();
using (var con = new System.Data.SqlClient.SqlConnection(SQL_CONNECTION))
{
con.Open();
using (var cmd = new System.Data.SqlClient.SqlCommand("SELECT * FROM MyTable;", con))
{
table.Load(cmd.ExecuteReader());
}
}
return table;
}
private int SaveApproved(int rowID, bool approved)
{
using (var con = new System.Data.SqlClient.SqlConnection(SQL_CONNECTION))
{
con.Open();
using (var cmd = new System.Data.SqlClient.SqlCommand("UPDATE MyTable SET IsApproved=#IsApproved WHERE ID=#ID;", con))
{
cmd.Parameters.Add("#IsApproved", SqlDbType.Bit).Value = approved;
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = rowID;
return cmd.ExecuteNonQuery();
}
}
}
I have a datagrid view and it's datasource is MS Access(which have a datatype, currency, date/time, and numbers), It shows data in the database but doesn't show other data types, only words or any string, here is my code for adding rows
string[] rowData = new string[columnCount];
while (dr.Read())
{
for (int k = 0; k < columnCount; k++)
{
if (dr.GetFieldType(k).ToString() == "System.int32")
{
rowData[k] = dr.GetInt32(k).ToString();
}
if (dr.GetFieldType(k).ToString() == "System.String")
{
rowData[k] = dr.GetString(k);
}
}
dataGridView1.Rows.Add(rowData);
}
can you help me with this? thanks
Instead of using the code above, I use this code, and it works
private void Form6_Load(object sender, EventArgs e)
{
loadData();
}
private void loadData()
{
str = new OleDbConnectionStringBuilder();
str.Provider = "Microsoft.ace.Oledb.12.0";
str.DataSource = #"\\sisc-erelim\4_Printing\VTDB\DB\VirginiTEADB2.accdb";
con = new OleDbConnection(str.ConnectionString);
dataGridView1.DataSource = fillTable("Select* from Accountstbl");
dataGridView1.Columns["Password"].Visible = false;
dataGridView1.Columns["Picture"].Visible = false;
}
private DataTable fillTable(string sql)
{
DataTable datatable = new DataTable();
using (OleDbDataAdapter da = new OleDbDataAdapter(sql, con))
{
da.Fill(datatable);
}
return datatable;
}