When button_click event is fired. I get DataTable from method and assign it to DataTable defined in class, but this DataTable setting in nothing. If I bind DataTable to GridView it show data.
public partial class Default : System.Web.UI.Page
{
TestClass test = new TestClass();
DataTable _table = new DataTable();
protected void Button1_Click(object sender, EventArgs e)
{
_table = test.getTable();
//displaying table
GridView1.DataSource= _table;
GridView1.DataBind();
}
protected void Button2_Click(object sender, EventArgs e)
{
//does not displaying table
GridView2.DataSource= _table;
GridView2.DataBind();
}
}
When I want get some data from _table, it have nothing. What's wrong?
Update:
Thanks all, and especially Darren Davies, problem been in Postback. When Button2_Click event happens _table assign _table = new DataTable(), and therefore _table no more reference to table returned by method getTable().
It will only bind correctly if Button1 is clicked before Button2. Otherwise _table will not be populated.
You should check that _table has data or call the getTable method inside the Button2_Click event handler:
protected void Button2_Click(object sender, EventArgs e)
{
_table = test.getTable();
GridView2.DataSource= _table;
GridView2.DataBind();
}
What you could try is this:
protected void Button1_Click(object sender, EventArgs e)
{
_table = test.getTable();
//displaying table
GridVieuw1.Datasource = null;
GridView1.DataSource= _table;
GridView1.DataBind();
}
Also you must do this at buuton 2
protected void Button2_Click(object sender, EventArgs e)
{
_table = test.getTable();
//displaying table
GridVieuw2.Datasource = null;
GridView2.DataSource= _table;
GridView2.DataBind();
}
Otheriwse the table is empty at button 2, so you have to press button 1 to fill it
Maybe that can do the trick
You are initializing your DataTable like
DataTable _table = new DataTable();
Then, when you click your button 1:
protected void Button1_Click(object sender, EventArgs e)
{
_table = test.getTable(); // <- here
//displaying table
GridView1.DataSource= _table;
GridView1.DataBind();
}
you are assigning your DataTable to a different instance.
You have to debug and check that your method getTable is returning a valid DataTable (and if you want to see your data, make sure that it contains data.
Your problem arises when you do not press button 1 before button 2. You should generalized your data binding like this:
public partial class Default : System.Web.UI.Page
{
TestClass test = new TestClass();
DataTable _table = new DataTable();
protected void Button1_Click(object sender, EventArgs e)
{
FillDataTable (); // <----------- See this function call
//displaying table
GridView1.DataSource= _table;
GridView1.DataBind();
}
protected void Button2_Click(object sender, EventArgs e)
{
FillDataTable (); // <----------- See this function call
//does not displaying table
GridView2.DataSource= _table;
GridView2.DataBind();
}
private void FillDataTable()
{
if(_table.Rows.Count == 0)
_table = test.getTable();
}
}
It would a wise way to fill table once, instead of filling on every button click and write it down in every button click event.
Related
Im begginer in c # and I try to do a spin code that I found on the net.
My worry is that I would like the value of the first line of the datagrid, automatically loads itself when launching the form in a textbox.
I have this code that works fine, but it does not display any value in the textbox if I do not click on a datagrid line.
The code :
namespace SQLiteTEST
{
public partial class Form1 : Form
{
private SQLiteConnection connection;
private String SQLSelect = "SELECT * FROM User";
public Form1()
{
InitializeComponent();
connection = new SQLiteConnection("Data Source=BddTest.s3db;Version=3;");
}
private void search()
{
dataGrid1.RowEnter -= dataGrid_RowEnter;
if (connection.State != ConnectionState.Open)
connection.Open();
SQLiteCommand command = connection.CreateCommand();
command.CommandText = SQLSelect;
DataTable dt = new DataTable();
SQLiteDataAdapter da = new SQLiteDataAdapter(command);
da.Fill(dt);
dataGrid1.DataSource = dt;
connection.Close();
dataGrid1.RowEnter += dataGrid_RowEnter;
}
private void dataGrid_RowEnter(object sender, DataGridViewCellEventArgs e)
{
int ID = int.Parse(dataGrid1.Rows[e.RowIndex].Cells[0].Value.ToString());
String Data1 = (String)dataGrid1.Rows[e.RowIndex].Cells[1].Value;
txtId.Text = ID.ToString();
txtName.Text = Data1;
}
private void Form1_Load(object sender, EventArgs e)
{
search();
}
private void dataGrid_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
MessageBox.Show("erreur");
}
private void button1_Click(object sender, EventArgs e)
{
var form_programme = new Form2();
form_programme.Show();
this.Hide();
}
private void dataGrid1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void txtName_TextChanged(object sender, EventArgs e)
{
}
private void txtId_TextChanged(object sender, EventArgs e)
{
}
private void dataGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
}
}
How could I make the first line appear in the textbox as if I was clicking on it?
Thank you in advance for your advice or sample code.
Regard.
Create a method like this:
private object GetValue(int rowIndex, int columnIndex)
{
return dataGrid1.Rows[rowIndex].Cells[columnIndex].Value;
}
I would like the value of the first line of the datagrid, automatically loads itself when launching the form in a textbox.
Use that to get any value you need. In your search method, at the end, after the data is loaded into the grid, you just need to get the values from the first row:
// first row first column.
// Use TryParse if the value is not always a number. If always a number
// then Parse is good enough
int id = int.Parse(GetValue(0, 0).ToString());
string data1 = (String) GetValue(0, 1);
txtId.Text = id.ToString();
txtName.Text = data1;
Also use .NET naming conventions so your local variables should be camel case and your method names should be Pascal notation. search should be Search.
Finaly i find how to resolve my problem !
Ill do this :
public Form1()
{
InitializeComponent();
connection = new SQLiteConnection("Data Source=BddTest.s3db;Version=3;");
search();}
Regard.
The following code is not saving the changes from the dataset to the database via the dataadapter.update(). I display the data on a winform to text boxes.
I have a save button that should save the changes made to the database. the changes are only saved to the in memory copy of the dataset. what am i missing to get this to save the changes to the database?
public partial class Frm_Main : Form
{
DataSet ds = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter();
BindingSource binding_Login = new BindingSource();
SqlCommandBuilder builder = new SqlCommandBuilder();
SqlConnection connection = new SqlConnection();
SqlCommand sqlcommand = new SqlCommand();
public Frm_Main()
{
InitializeComponent();
}
private void FrmMain_Load(object sender, EventArgs e)
{
this.Text = "Main (" + GlobalVars.username.ToString() + ")";
this.AcceptButton = btnSearch;
connection.ConnectionString = GlobalVars.sqlConnString;
}
private void FrmMain_Close(object sender, EventArgs e)
{
Close();
}
private void btnSearch_Click(object sender, EventArgs e)
{
if(!string.IsNullOrEmpty(txtSearch.Text))
{
Search();
}
}
public void Search()
{
string sqlcommandstring = "select * from login where loginname like #search;";
connection.Open();
sqlcommand.CommandText = sqlcommandstring;
sqlcommand.Connection = connection;
sqlcommand.Parameters.AddWithValue("#search", "%" + txtSearch.Text + "%");
adapter.SelectCommand = sqlcommand ;
builder.DataAdapter = adapter;
adapter.Fill(ds,"Login") ;
BindControls();
txtLoginName.DataBindings.Add(new Binding("Text", binding_Login, "LoginName"));
txtPassword.DataBindings.Add(new Binding("Text", binding_Login, "Password"));
adapter.UpdateCommand = builder.GetUpdateCommand();
adapter.DeleteCommand = builder.GetDeleteCommand();
adapter.InsertCommand = builder.GetInsertCommand();
}
private void btnNext_Click(object sender, EventArgs e)
{
binding_Login.MoveNext();
}
protected void BindControls()
{
binding_Login.DataSource = ds.Tables[0];
}
private void btnPrevious_Click(object sender, EventArgs e)
{
binding_Login.MovePrevious();
}
private void btnSave_Click(object sender, EventArgs e)
{
ds.AcceptChanges();
adapter.Update(ds.Tables[0]);
}
}
I was able to resolve the issue by changing the save buttons click event to the following:
private void btnSave_Click(object sender, EventArgs e)
{
this.binding_Login.EndEdit();
adapter.Update(this.ds.Tables[0]);
}
The problem was in this line:
private void btnSave_Click(object sender, EventArgs e)
{
ds.AcceptChanges();//EDIT This is the problem!
adapter.Update(ds.Tables[0]);
}
I had a similar problem and during debbuging I realized that if you call .AcceptChanges() before DataAdapter.Update(), all your modified rows will change their status to Unchanged. This means that DataAdapter.Update() will lose all the flags it needs to pick the right INSERT, UPDATE, DELETE command.
I also had problems using editing batches like:
row.BeginEdit();
// Modify several rows
row.EndEdit();
As I understand, the problem here happens because all changes are reserved until you call the AcceptChanges() method, thus causing all the row state flags to be set as Unchanged, making DataAdapter.Update() essentially blind.
In short:
Create a DataAdapter.
Set the InsertCommand, UpdateCommand, DeleteCommand, SelectCommand.
Fill a DataSet, DataTable, DataRow[], with the adapter.
Make changes to your DataSet, DataTable, DataRow[].
Make sure these changes are flagged in the RowState property of the modified row(s).
To ensure this, don't use batch editing, and don't call AcceptChanges(), before the DataAdapter.Update() method.
Using the same adapter, call adapter.Update(DataSet|DataTable|DataRow[]).
When trying to update GridView data, it successfully runs, but it gets the old data instead of the data you type in the textboxes.
This is what I have:
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
string name = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[1].Controls[0])).Text;
string phone = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[2].Controls[0])).Text;
string email = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[3].Controls[0])).Text;
int contactId = Convert.ToInt32(((TextBox)(GridView1.Rows[e.RowIndex].Cells[4].Controls[0])).Text);
objLogic.UpdateContact(name, phone, email, contactId); //passes values to SQL to update database
GridView1.EditIndex = -1;
GridView1.DataBind();
}
and
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
GridView1.DataBind();
}
and
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DropDownList1.DataSource = objLogic.LoadClient();
DropDownList1.DataTextField = "name";
DropDownList1.DataValueField = "clientId";
DropDownList1.DataBind();
}
GridView1.DataSource = objLogic.LoadContacts(Convert.ToInt16(DropDownList1.SelectedValue));
GridView1.DataBind();
For example, the current data is:
name: Blake, phone: 123-234-3456, email: test#test.com, contactId: 22
I type in new data:
name: John, phone: 555-555-5555, email: test2#test2.com, contactId: 22
Data that ends up in the database:
name: Blake, phone: 123-234-3456, email: test#test.com, contactId: 22
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DropDownList1.DataSource = objLogic.LoadClient();
DropDownList1.DataTextField = "name";
DropDownList1.DataValueField = "clientId";
DropDownList1.DataBind();
BindGrid();
}
}
protected void BindGrid()
{
GridView1.DataSource = objLogic.LoadContacts(Convert.ToInt16(DropDownList1.SelectedValue));
GridView1.DataBind();
}
Every time the page posts back you are rebinding the grid. Move the binding of the grid into a separate function. After you do the row updating, rebind the grid.
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
string name = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[1].Controls[0])).Text;
string phone = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[2].Controls[0])).Text;
string email = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[3].Controls[0])).Text;
int contactId = Convert.ToInt32(((TextBox)(GridView1.Rows[e.RowIndex].Cells[4].Controls[0])).Text);
objLogic.UpdateContact(name, phone, email, contactId); //passes values to SQL to update database
GridView1.EditIndex = -1;
BindGrid();
}
When you edit you must call BindGrid too.
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
//GridView1.DataBind(); this is meaningless, you have not set a DataSource
BindGrid();
}
When you raise the RowUpdating event your basically getting the values BEFORE the GridView updates the row. This is basically so you can cancel the update operation. To get what you've type in I think you need to get the new values (the Dictionary e.NewValues() in your case).
In your case you can use it something like this (assuming name, phone and email are what they're called in your gridview):
foreach(DictionaryEntry de in e.NewValues())
{
string name = de.FirstOrDefault(x => x.Key == "name").Value;
string phone = de.FirstOrDefault(x => x.Key == "phone").Value;
string email = de.FirstOrDefault(x => x.Key == "email").Value;
}
NOTE: If you're simply using this to get the values typed in to update your database then you're better of binding the datagrid and use the value after that to ensure you definitely have the same values in the datagrid as to what you put into the database. Alternatively, use the RowUpdated event instead of the RowUpdating event.
The most prevalent reason is that we usually forgot to check the postbacks in the Page Load event.
check the post-back, then the problem will be removed.
if (! IsPostBack)
{
readData();
...
}
Prokzy I have just your example on my side and doing something like this worked fine for me. notice the DataSource portion. I have a DataSet instantiated as aDataSet btw
protected void GridView1_GridViewPageEventArgs e(object sender, GridViewPageEventArgs e)
{
GridView1.EditIndex = e.NewPageIndex;
GridView1.DataSource = null;
GridView1.DataSource = aDataset;
GridView1.DataBind();
}
You need to call LoadContacts again and reassign GridView1.DataSource after the database is updated. Currently, the DataSource is not being updated - and is just using the collection that was retrieved prior to the row update.
The following code gives me to take one row value from textbox to datagridview ......
private void button1_Click(object sender, EventArgs e)
{
DataTable table = new DataTable();
table.Columns.Add("Course Name", typeof(string));
table.Columns.Add("Credit", typeof(string));
table.Rows.Add(txtName.Text.Trim(), txtCredit.Text.Trim());
addcrsView.DataSource = table;
}
When I give another value to textbox it just replaces the previous one. But I need to take both in datagrid view.
As I am very beginner please put your answer details.
You have to make table as class level object.
DataTable table = new DataTable();
And, set the DataGridView datasource in the Form_Load event
private void Form1_Load(object sender, EventArgs e)
{
table.Columns.Add("Course Name", typeof(string));
table.Columns.Add("Credit", typeof(string));
addcrsView.DataSource = table;
}
Your button1_Click just need to add row
private void button1_Click(object sender, EventArgs e)
{
table.Rows.Add(txtName.Text.Trim(), txtCredit.Text.Trim());
}
I have populated a list box using a Data-table.
In another method, I have to retrieve the data table from the list box.
Datatable dt = (DataTable)lstExample.DataSource;
Throws an error, that the Datatable dt is null
I am working on c# ASP.Net
If you are trying to do this on a Postback then the DataTable will no longer be there. You will need to save it in ViewState or Session if you want access to it on a Postback, or just hit the database again.
For example:
protected override Page_Load(object sender, EventArgs e)
{
if( !IsPostBack)
{
DataTable tbl = GetData();
lstData.DataSource = tbl;
lstData.DataBind();
// store in viewstate
ViewState["data"] = tbl;
}
}
protected void btnSave_Click(object sender, EventArgs e)
{
DataTable tbl = (DataTable)ViewState["data"];
}