Datagrid refresh not working - c#

I have a datagrid to display some information from a SQL table, and then a simple textbox and button to allow users to add records to the database. Problem is, when the user clicks Add, the datagrid SHOULD update, but it doesn't, any ideas? The code in question is as follows:
protected void Page_Load(object sender, EventArgs e)
{
username.Text = Session["username"].ToString();
datetime.Text = DateTime.Now.ToString();
BindData();
}
protected void BindData()
{
string SQLQuery = "SELECT * From Filters";
OleDbConnection MyConn = new OleDbConnection(ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);
DataSet resultsDataSet = new DataSet();
MyConn.Open();
OleDbDataAdapter DataAdapter = new OleDbDataAdapter(SQLQuery, MyConn);
DataAdapter.Fill(resultsDataSet);
DGFilters.DataSource = resultsDataSet;
DGFilters.DataBind();
if (resultsDataSet.Tables[0].Rows.Count == 0)
{
no_records.Visible = true;
DGFilters.Visible = false;
}
else
{
DGFilters.Visible = true;
no_records.Visible = false;
}
MyConn.Close();
}
protected void AddFilter_Click(object sender, EventArgs e)
{
OleDbConnection MyConn = new OleDbConnection(ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);
MyConn.Open();
string SQLInsert = "INSERT INTO Filters (FilterString) VALUES ( '" + FilterToAdd.Text + "')";
OleDbCommand MyCmd = new OleDbCommand(SQLInsert, MyConn);
MyCmd.ExecuteNonQuery();
MyConn.Close();
DataBind();
}
Any ideas?

At the bottom of your AddFilter_Click method you need to call your own BindData() so the grid can be refreshed with the new record. Right now you're calling DataBind(), which is a method on the base class Control, which is being applied to your entire web form. I'm guessing this isn't doing much of anything.
Also, in your Page_Load method, you can probably change this:
BindData();
to
if (!Page.IsPostBack)
BindData();
so that you don't bind your grid twice when the user clicks on the 'add' button.

Related

Updating/saving data to an SQL database table using c# winforms

I'll start off by saying that I'm pretty inept at coding (have yet to learn how to utilize classes and how they work in depth), and that I've never worked with sql before doing this project.
The idea here is that you connect to an sql database, after which a datagridview element gets filled with data from a table called TABLE_1 by default. The user should then be able to input, delete and save data.
The first two work operations work perfectly, but the saving is the problem. I've banged my head against a wall for about 4 days trying to get the saving to work, but I just cant get it to do so. The saving is done with the method Button3_click.
Any insight as to what I should do?
Is the main chunk of the code where you connect the part where I'm
messing up?
//initialize the classes I guess, on some youtube guides they did so
SqlConnection con;
DataSet ds;
SqlDataAdapter a;
DataTable t;
SqlCommandBuilder scb;
static string tablename = "TABLE_1";
string constring;
//connect button
private void button1_Click(object sender, EventArgs e)
{
try
{
//connect using info from textboxes, connection is ok
constring = "server=" + Server.Text + ";database=" + DB.Text + ";UID=" + UID.Text + ";password=" + Password.Text;
SqlConnection con = new SqlConnection(constring);
con.Open();
DataSet ds = new DataSet();
Save.Enabled = true;
//check if table name is empty, if so default to TABLE_1
if (textBox1.Text != "")
{
tablename = textBox1.Text;
}
else
{
tablename = "TABLE_1";
}
a = new SqlDataAdapter("SELECT * FROM " + tablename, con);
DataTable t = new DataTable();
a.Fill(t);
datagrid.DataSource = t;
//
label5.Text = Server.Text;
con.Close();
}
catch(Exception es)
{
MessageBox.Show(es.Message);
}
}
//save button
private void button3_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(constring);
con.Open();
DataSet ds = new DataSet();
DataTable t = new DataTable();
a.TableMappings.Add(tablename, "t");
scb = new SqlCommandBuilder(a);
a.Update(t);
con.Close();
}
Use the following example which sets up the adapter, dataset and table name as private variables.
Also, I recommend to never use one letter variable names as a) it's difficult to debug b) when getting into more lines of code it's going to be difficult to know what a variable is for.
Next up, using SELECT *, it' unknown if you have setup a auto-incrementing primary key which is needed to perform updates. In the example below, Id is auto-incrementing.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace WindowsFormsDataAdapterExample
{
public partial class Form1 : Form
{
private SqlDataAdapter _companiesSqlDataAdapter;
private DataSet _companiesDataSet;
private string _tableName = "Companies";
public Form1()
{
InitializeComponent();
Shown += OnShown;
}
private void OnShown(object sender, EventArgs e)
{
_companiesDataSet = new DataSet();
_companiesSqlDataAdapter = new SqlDataAdapter(
"SELECT Id, FirstName, LastName, PhoneNumber, City FROM dbo.Companies;",
"Data Source=.\\sqlexpress;Initial Catalog=ForumExample;" +
"Integrated Security=True");
var builder = new SqlCommandBuilder(_companiesSqlDataAdapter);
_companiesSqlDataAdapter.Fill(_companiesDataSet, _tableName);
dataGridView1.DataSource = _companiesDataSet.Tables[_tableName];
}
private void SaveButton_Click(object sender, EventArgs e)
{
_companiesSqlDataAdapter.Update(_companiesDataSet, _tableName);
}
}
}

Visual C# Datagrid returning all records from database

I want to display a datagrid that will return records based on a query from my search button but whenever I click the search button, it returns all the records from the database.
HTML
<html>
<asp:TextBox ID="ClientCode" runat="server"></asp:TextBox>
<asp:GridView ID="ClientDataGrid" runat="server" Height="111px"
Width="202px" Visible="False"></asp:GridView>
C#
private void rep_bind()
{
connection();
string query = ""select * from client where client_code ='" +
ClientCode.Text + "'";
SqlDataAdapter da = new SqlDataAdapter(query, con);
DataSet ds = new DataSet();
da.Fill(ds);
ClientDataGrid.DataSource = ds;
ClientDataGrid.DataBind();
}
private void InitializeComponent()
{
}
protected void search_Click(object sender, EventArgs e)
{
Label1.Text = "";
connection();
string query = string.Format("select * from client where client_code
='" + ClientCode.Text + "'") ; ;
SqlCommand com = new SqlCommand(query, con);
com.Parameters.Add("#category", SqlDbType.NVarChar, 20).Value =
category.SelectedItem.Text;
SqlDataReader dr;
dr = com.ExecuteReader();
ListItem selectedItem = category.SelectedItem;
if (string.IsNullOrWhiteSpace(ClientCode.Text) &&
string.IsNullOrWhiteSpace(ClientName.Text))
{
ClientDataGrid.Visible = false;
Label1.Visible = true;
Label1.Text = "Please Enter Correct Search Values";
}
else if (dr.HasRows)
{
dr.Read();
rep_bind();
ClientDataGrid.Visible = true;
}
else
{
ClientDataGrid.Visible = false;
}
}
I want to display records that will match the client code on the text box but it always return all the records from the database.
I'm unable to comment on the actual question so I'll ask it here.
You seem to be executing the same query twice. Once to see if it has any rows and the second time to fill the data grid. You can change this so that the query is executed only once.
One way to prevent SQL injection attacks is to use a Stored Procedure instead of directly creating the query using string interpolation. Use a stored procedure and pass your conditions using parameters.
Here's a link that explains how to create one
https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/create-a-stored-procedure
How about this version?
using System;
using System.Data;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
SqlCommand sCommand;
SqlDataAdapter sAdapter;
SqlCommandBuilder sBuilder;
DataSet sDs;
DataTable sTable;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string connectionString = "Data Source=.;Initial Catalog=pubs;Integrated Security=True";
string sql = "SELECT * FROM Stores";
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
sCommand = new SqlCommand(sql, connection);
sAdapter = new SqlDataAdapter(sCommand);
sBuilder = new SqlCommandBuilder(sAdapter);
sDs = new DataSet();
sAdapter.Fill(sDs, "Stores");
sTable = sDs.Tables["Stores"];
connection.Close();
dataGridView1.DataSource = sDs.Tables["Stores"];
dataGridView1.ReadOnly = true;
save_btn.Enabled = false;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
}
private void new_btn_Click(object sender, EventArgs e)
{
dataGridView1.ReadOnly = false;
save_btn.Enabled = true;
new_btn.Enabled = false;
delete_btn.Enabled = false;
}
private void delete_btn_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Do you want to delete this row ?", "Delete", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
dataGridView1.Rows.RemoveAt(dataGridView1.SelectedRows[0].Index);
sAdapter.Update(sTable);
}
}
private void save_btn_Click(object sender, EventArgs e)
{
sAdapter.Update(sTable);
dataGridView1.ReadOnly = true;
save_btn.Enabled = false;
new_btn.Enabled = true;
delete_btn.Enabled = true;
}
}
}

search an item by name and display the content in another page

I want to display an item information in gridview from data base by using it name , and i want the gridview to be in another page
i tried this code,,but it didn't work
in the first page
protected void Page_Load(object sender, EventArgs e)
{
}
public string txt
{
get
{
// Return the actual name if it is not null.
return TextBox1.Text ?? string.Empty;
}
}
}
in the second page
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=FATIMAH;Initial Catalog=makeup;Integrated Security=True");
string find = "select * from product where(name like '%' +#name+ '%')";
SqlCommand comm = new SqlCommand(find, con);
comm.Parameters.Add("#name", SqlDbType.NChar).Value = txt;
con.Open();
comm.ExecuteNonQuery();
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = comm;
DataSet ds = new DataSet();
da.Fill(ds, "name");
GridView1.DataSource = ds;
GridView1.DataBind();
con.Close();
}
}
You can pass parameter to another page using QueryString. onclick event of button on First page do this:-
protected void Button1_Click(object sender, EventArgs e)
{
string search_word = TextBox1.Text.ToString();
Response.Redirect("~/secondpage.aspx?srch_word=" + search_word);
}
and on second page request the querystring:-
protected void Page_Load(object sender, EventArgs e)
{
string search = Request.QueryString["srch_word"];
//execute sql query to perform search operation
}
Your query looks off to me. Try "select * from product where name like '%#name%'"
Also for your parameters you can just cmd.Parameters.AddWithValue("name", nameVariable);
Not sure why you would need to specify the type in this situation.
your problem is not the SQL query, your problem is passing parameter to another page.
for this reason you can do it in at least 4 different ways.
Send Text by query string
Pass it via Post Data
Pass it via Cookie
Send it via Session
in this case you can use query string, but you have to care about security issue.
BTW, it depends on how you redirect to 2th page.

Update datagridview from SQL in the form close event

I have a form with a dataGridView1 that is updated from SQL database.
What i am trying to do is: when the user presses the Close button I am checking a variable and if condition is true then I cancel the from close (e.Cancel = true;) and i want to display some data in the datagrid.
Whatever I do the grid is not updating. I am calling a "private void update()" to update the grid from SQL but after I cancel the form close event but it does not seem to work.
I have tried refreshing the form, refreshing the datagrid with no result.
After the form_Close even finishes, and the datagrid is empty, if i press a button that calls the same "private void update()" it works and the data is shown in the datagrid.
Thank you for your help.
EDIT1: to give you more details
I tried the code on FormClosing but I get no result.
The code I'm using is:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
getdata_fromSQL();//this private void gets some data from sql into the datagrid
if (dataGridView1.RowCount > 0)//check if i have at least one row retreved
{
// Cancel the Closing event and tell the user
MessageBox.Show("Please check the data before leaving.");
e.Cancel = true;
getdata_fromSQL();// retrieve the data again for the user to see (this part is not working
}
}
This is how the data is retrieved.
private void getdata_fromSQL()
{
SqlConnection con = new SqlConnection("connection string"); //defining connection
con.Open();
string sql_command = "Select * from Test_Table where [Check] is null";
SqlCommand command = new SqlCommand(sql_command, con); // defining the command
DataSet set = new DataSet("SQL_table");
SqlDataAdaptersda = new SqlDataAdapter(command); //defining the adapter and make it accept changes
sda.AcceptChangesDuringFill = true;
sda.AcceptChangesDuringUpdate = true;
set.Clear(); //just to make sure my adapter is empty
cmdBuilder = new SqlCommandBuilder(sda); //creating the command builder so I can save the changes
sda.Fill(set, "SQL_table"); // fill the dataset
dataGridView1.DataSource = set;
dataGridView1.DataMember = "SQL_table"; //fill datagrid
dataGridView1.CellValueChanged -= dataGridView1_CellValueChanged;
dataGridView1.CellValueChanged += dataGridView1_CellValueChanged; //look for cell value changed (I am using this in other scope)
}
After I cancel the close and try to update the datagrid again, it remains blank.
EDIT2: #Gami
your code does this:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (i == 1)
{
MessageBox.Show("Hello");
e.Cancel = true;
getRefresh();
}
}
and your refresh is this:
private void getRefresh()
{
SqlConnection con = new SqlConnection(#"user id=testuser;" +
"password=testpass;Data Source=SERVER;" +
// "Trusted_Connection=yes;" +
"Initial Catalog=Partner_database; " +
"connection timeout=30"); //defining connection
con.Open();
SqlCommandBuilder cmdBuilder;
string sql_command = "Select * from Test_table where [Check] is null";
SqlCommand command = new SqlCommand(sql_command, con); // defining the command
DataSet set = new DataSet("SQL_table");
SqlDataAdapter sda = new SqlDataAdapter(command); //defining the adapter and make it accept changes
sda.AcceptChangesDuringFill = true;
sda.AcceptChangesDuringUpdate = true;
set.Clear(); //just to make sure my adapter is empty
cmdBuilder = new SqlCommandBuilder(sda); //creating the command builder so I can save the changes
sda.Fill(set,"SQL_table"); // fill the dataset
dataGridView1.DataSource = set;
dataGridView1.DataMember = "SQL_table"; //fill datagrid
}
My code is the one above. We are both using the FormClosing event, we both cancel the close process, and then call the refresh.
This is the SQL table:
This is the datasource for my datagrid:
Try to write code in Form1_FormClosing() event of form
example is
namespace canceldemo
{
public partial class Form1 : Form
{
int i = 1;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (i == 1)
{
MessageBox.Show("Hello");
e.Cancel = true;
}
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = (i+10).ToString();
}
}
}
I have found the issue.
Looks like it was a mistake on my side, I still don't know why is not working the way it is, but know the cause.
I am using code to get the logged user name from Windows, and when i filter the SQL table i filter on the user as well.
This is the code to retrieve the user:
private string getUserDisplayName()
{
var username = new StringBuilder(1024);
uint userNameSize = (uint)username.Capacity;
// try to get display name and convert from "Last, First" to "First Last" if necessary
if (0 != GetUserNameEx(3, username, ref userNameSize))
return Regex.Replace(username.ToString(), #"(\S+), (\S+)", "$2 $1");
// get SAM compatible name <server/machine>\\<username>
if (0 != GetUserNameEx(2, username, ref userNameSize))
{
IntPtr bufPtr;
try
{
string domain = Regex.Replace(username.ToString(), #"(.+)\\.+", #"$1");
DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, domain);
DomainController dc = DomainController.FindOne(context);
if (0 == NetUserGetInfo(dc.IPAddress,
Regex.Replace(username.ToString(), #".+\\(.+)", "$1"),
10, out bufPtr))
{
var userInfo = (USER_INFO_10)Marshal.PtrToStructure(bufPtr, typeof(USER_INFO_10));
return Regex.Replace(userInfo.usri10_full_name, #"(\S+), (\S+)", "$2 $1");
}
}
finally
{
NetApiBufferFree(out bufPtr);
}
}
return String.Empty;
}
In my FormClosing block i am calling this private void and use this as filter to sql.
user_name = getUserDisplayName();
string sql_command = "Select * from Test_table where [Check] is null and [User Name] = '" + user_name + "'";
When removing the getUserDisplayName() call it works. When i call it it does not refresh the grid even if it runs with no error.
Does it cut my connections when i press the close button? I think this is another question and here is off topic.

ArguementOutOfRangeException was unhandled error

i'm very new to programming and c#. here i'm having ArguementOutOfRangeException. i want to add a new data row to the datagridview every time when click the button. so i used a variable "i" to increase the value one by one and change the row value when i use "0" which means
dataGridView2.Rows[0].Cells[0].Value = textBox1.Text.ToString();
instead of "i" the first row fills but when use "1" which means
dataGridView2.Rows[1].Cells[0].Value = textBox1.Text.ToString();
the exception comes. what is the right way to do such a thing ?
namespace WindowsFormsApplication1
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public SqlConnection conn;
public int i = 0;
private void Form2_Load(object sender, EventArgs e)
{
conn = new SqlConnection("Data Source=.\\SQLEXPRESS; Integrated Security=sspi; Initial Catalog=student");
conn.Open();
}
private void button1_Click(object sender, EventArgs e)
{
string Sqlstr = "insert into student(name, pw)values(#name,#pw)";
SqlCommand cmd = new SqlCommand(Sqlstr, conn);
cmd.Parameters.AddWithValue("#name", textBox1.Text);
cmd.Parameters.AddWithValue("#pw", textBox2.Text);
if (cmd.ExecuteNonQuery() > 0)
{
i++;
DataGridView dataGridView1 = new DataGridView();
dataGridView2.Rows[i].Cells[0].Value = textBox1.Text.ToString();
dataGridView2.Rows[i].Cells[1].Value = textBox2.Text.ToString();
}
label1.Text = Convert.ToString(i);
}
}
}
You don't have to define a new DataGridView each time on a button click, I believe you want to add a new row in your existing DataGridView after the insert in database. You can do:
if (cmd.ExecuteNonQuery() > 0)
{
DataGridViewRow row = (DataGridViewRow)dataGridView2.Rows[0].Clone();
row.Cells[0].Value = textBox1.Text.ToString();
row.Cells[1].Value = textBox2.Text.ToString();
dataGridView2.Rows.Add(row);
}
You have to add new rows before you try writing in them. Use dataGridView2.Rows.Add( something ), check out the Add method.

Categories

Resources