Using C# and Winform.
I read a couple of similar questions but couldn't find any great answers that could interlock with my code. So, bear with me and thank you in advance for helping me.
I have a single form that contains multiple User Controls. Inside the first user control, you can insert, update and delete records from the database. In the second User Control, there is a datagridview that is populated with all records.
The problem I have is that whenever I insert, update or delete a record inside the first user control. It won't refresh inside the datagridview when I swap to the second user control.
Beneath is the second user control that populates the datagridview
private void populate()
{
database.OpenConnection();
string query = "SELECT id, name, qoute, time, date from maintable";
SQLiteDataAdapter sda = new SQLiteDataAdapter(query, database.connection);
SQLiteCommandBuilder builder = new SQLiteCommandBuilder(sda);
var ds = new DataSet();
sda.Fill(ds);
dtgNav.DataSource = ds.Tables[0];
databas.CloseConnection();
}
private void Navigation_Load(object sender, EventArgs e)
{
populate();
dtgNav.Columns[0].HeaderText = "ID";
}
public void Refresh()
{
this.Refresh();
}
Beneath is the code for adding a record to the datagridview in the first user control
private void btnAdd_Click(object sender, EventArgs e)
{
database.OpenConnection();
string query = "INSERT INTO maintable (`id`, `name`, `qoute`, `time`,`date`) VALUES (#Id, #Name, #Qoute, #Time, #Date)";
SQLiteCommand command = new SQLiteCommand(query, database.connection);
command.Parameters.AddWithValue("#Id", tbxID.Text);
command.Parameters.AddWithValue("#Name", tbxName.Text.Trim());
command.Parameters.AddWithValue("#Qoute", tbxQoute.Text.Trim());
command.Parameters.AddWithValue("#Time", tbxTime.Text.Trim());
command.Parameters.AddWithValue("#Date", dtpDate.Value.ToString("yyyy-MM-dd"));
command.ExecuteNonQuery();
MessageBox.Show("Added new event into the database.");
database.CloseConnection();
usercontrol2.Refresh();
}
I would appreciate it if we found a way to refresh the datagridview when the button is clicked without changing the original code all too much.
You have a public void Refresh method in the second usercontrol, try modifying this.Refresh();, to say populate();. this should call your private void populate method that you called when loading which should reload the grid. Let me know if this helps.
Related
I've create a datagridview that show me my data. Then I should click on a row and I'd like to show a form where I can update my values.
Is it possible go to the previous/next element of the datagridview in another form? Because I'd like to create two buttons that allow me to scan the whole table and update each value.
Can you help me, please? I really don't know where to start
EDIT: This is the code to show my data
public static string StringaConnessione = "Data Source=localhost;Database=db;userid=root;password='';";
public static MySqlConnection Connessione = new MySqlConnection(StringaConnessione);
void MostraBtnClick(object sender, EventArgs e)
{
Connessione.Open();
MySqlDataAdapter SDA=new MySqlDataAdapter("SELECT * FROM Acquisti",Connessione);
DataTable DATA= new DataTable();
SDA.Fill(DATA);
dataGridView1.DataSource=DATA;
Connessione.Close();
I have a data app that uses a BindingNavigator. I have hooked up the navigator to a binding source, however it is not working. It will not add or delete rows. The binding source is: accountBindingSource. I don't understand what is wrong. I have the following code:
public partial class AccountDataGridView : Form
{
public AccountDataGridView()
{
InitializeComponent();
Setup();
}
private void AccountDataGridView_Load(object sender, EventArgs e)
{
// Change the back color of the first column. This can also be changed in the designer
accountGridView.Columns[0].DefaultCellStyle.BackColor = Color.FromArgb(192, 192, 255);
}
private void Setup()
{
// Define a global variable for the data table
Account = new DataTable(Text);
query = string.Format("SELECT * FROM {0}", Text);
// Establish a connection between the Database and the form
conn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Tutoring Database.accdb;Persist Security Info=False");
conn.Open();
// Setup data table
OleDbDataAdapter accountAdapter = new OleDbDataAdapter(query, conn);
if (accountAdapter != null)
{
accountAdapter.Fill(Account);
}
accountGridView.DataSource = Account;
conn.Close();
}
private void DataErrorRaised(object sender, DataGridViewDataErrorEventArgs e)
{
// Data table error handling. This is triggered when the user attempts to input invalid data into the CurrentBalance column
MessageBox.Show("You have entered an invalid data type for the currency column. Please enter text formatted like so: '$0.00'",
"Account Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
}
private void btnSave_Click(object sender, EventArgs e)
{
// Update Access Database
try
{
adapter.SelectCommand = new OleDbCommand(query, conn);
adapter.InsertCommand = new OleDbCommand(query, conn);
adapter.DeleteCommand = new OleDbCommand(query, conn);
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
adapter.Update(Account);
Console.WriteLine("Saved");
}
catch
{
}
}
private DataTable Account;
private string query;
private OleDbConnection conn;
private OleDbDataAdapter adapter = new OleDbDataAdapter();
private void accountGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
btnSave_Click(null, null);
}
}
In your question you assigned data to accountGridView.DataSource. So you can not expect the binding navigator work. The BindingSource is not connected to data and the BindingNavigator and DataGridView are not connected to the BindingSource.
You should perform these settings using designer or code:
Load data and assign data to DataSource property of BindingSource. (Using code)
Assign BindingSource to DataSource property of your DataGridView
Assign BindingSource to BindingSource property of the BindingNavigator.
Note
Changing query has nothing to do with binding source. The BindingSource and BindingNavigator work regardless of the adapter or anything which provides/saves data. Neither BindingSource nor BindingNavigator are not aware about where the data comes from actually and how the data will be saved.
I just solved my problem by creating a new BindingSource and setting its properties through code. To do this, simply drag a BindingSource onto the form. Name it whatever you would like. In the code part of your solution type something similar to this (in the constructor).
BindingSource.DataSource = Account;
Make sure to set your BindingNavigator's BindingSource to the BindingSource you just created. Thank you for the help, everyone!
EDIT: I don't know if this had anything to do with my solution but I also edited my queries a little bit. This code is mandatory for the project to work.
try
{
adapter.SelectCommand = new OleDbCommand(query, conn);
adapter.InsertCommand = new OleDbCommand("INSERT INTO Account (AccountNumber, LastName, FirstName, CurrentBalance) " +
"VALUES (?, ?, ?, ?)", conn);
adapter.DeleteCommand = new OleDbCommand(query, conn);
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
adapter.Update(Account);
Console.WriteLine("Saved");
}
catch
{
}
For posterity:
BindingNavigator's buttons are lightweight controls, unlike a real Button control.
When you click any button in the BindingNavigator, the Focus is not stolen from the current Control, and thus the sequence of events that lead to the data being pushed to the underlying database is never called.
I know I had an example of a few lines of code you had to put in each of those lightweight button's Click handler, but can't find it for now.
This has always been a PITA!
I have a list box that is populated by a query result set, i would to give the user the ability to edit the contents of the list box, and update the database back end, how can i achieve this?
public Brand_Manager(Main parent)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SqlConn"].ConnectionString.ToString());
SqlCommand cmd = new SqlCommand("select Brand_ID, Brand_Name from Brand where status=1", conn);
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable t = new DataTable();
da.Fill(t);
listBox1.DisplayMember = "Brand_Name";
listBox1.DataSource = t;
listBox1.ValueMember = "Brand_ID";
conn.Close();
}
private void Edit_Button_Click(object sender, EventArgs e)
{
this.Edit_Button.Enabled = false;
object item = listBox1.SelectedItem;
Edit_Brand frm = new Edit_Brand();
this.AddOwnedForm(frm);
frm.ShowDialog();
}
Do you use WPF or WinForms? Anyway you need to investigate Bindings: BindingSource in WinForms or Binding class in WPF (http://msdn.microsoft.com/en-us/library/ms750612.aspx).
Look at DataTable events http://msdn.microsoft.com/en-us/library/system.data.datatable_events.aspx . There is RowChangedEvent. Call update sql command in its handler.
You need to use datagridview for this purpose. It is designed for this purpose. You can assign the datasource to gridview and allow user to edit rows. Then by handling row edited event or by giving the button you can update the database. See an example here
When user select any record from the GridView then my DetailView is updated based on the selection of the GridView. So what I am trying to do is that when I delete anything from the DetailView then I want to refresh the GridView so basically I don’t want to show still the deleted record in the GridView. I have tried to resolve this issue by doing the data bind after my connection and SQL statement but it does not refresh it. One thing to note is that I am using a Accordion pane but both my gridview and the detailview are on the same pane. I am not sure if this is breaking anything. Here is my code:
protected void Refresh_ItemCommand(object sender, DetailsViewCommandEventArgs e)
{
if (e.CommandName.Equals("Delete", StringComparison.CurrentCultureIgnoreCase))
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
SqlDataAdapter da = new SqlDataAdapter("select ID, Name, Address from dbo.MyTable", con);
DataTable dt = new DataTable();
da.Fill(dt);
Gridview1.DataSource = dt;
Gridview1.DataBind();
}
}
You may use the event of the Data view called "ItemDeleted" as follows:
DetailViewName_ItemDeleted(object sender,
DetailsViewDeletedEventArgs e)
{
// Refresh the GridView control after a new record is updated
// in the DetailsView control.
GridViewName.DataBind();
}
The above code is from the official MSDN site for detail view control.
The other way (which I prefer) is to handle the data grid during the Page_load procedure so when you press your delete button in the detail view, the page will perform a postback.
So in the procedure Page_load you can call another procedure which fills the data grid. The code might be like this:
if (isPostback)
{
FillGrid();
}
private void FillGrid()
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
SqlDataAdapter da = new SqlDataAdapter("select ID, Name, Address from dbo.MyTable", con);
DataTable dt = new DataTable();
da.Fill(dt);
Gridview1.DataSource = dt;
Gridview1.DataBind();
}
Your code doesn't show anything where the record is actually deleted so it's understandable that when you re-fetch the data still contains everything.
What you need to do is:
Execute a sql statement to delete the record
Re-fetch the data
Rebind the data.
If you follow those 3 steps it will work.
try to use the event that is called in case of pressing the delete key from the DGV
private void DGV_DeleteKeyPressed(object sender, KeyEventArgs e)
{
//enter code here
}
So I've got a class, commenter, and two methods within that class, SaveBtn_Click - created primarily not by me, and then also PeerReview, primarily created by me.
Anyway, the code starts off like this (after a variety of using statements):
public partial class commenter : System.Web.UI.Page
{
string employee_reviewed;
PeerReview pr = new PeerReview();
public void SaveBtn_Click(object sender, EventArgs e)
{
//all the information for the SaveBtn_Click method.
}
After that, I have PeerReview:
public void PeerReview(System.Web.UI.WebControls.ListBox listbox)
{
MySqlConnection con = new MySqlConnection("server=localhost;database=hourtracking;uid=username;password=password");
MySqlCommand cmd = new MySqlCommand("select first_name from employee where active_status=1", con);
con.Open();
MySqlDataReader r = cmd.ExecuteReader();
Console.WriteLine("Another test!");
Console.WriteLine(r);
Console.WriteLine("Hi, this is a test!");
while (r.Read())
{
listbox.Items.Add(new ListItem(Convert.ToString(r["first_name"]), Convert.ToString(r["first_name"])));
}
con.Close();
}
I'm connecting this with ASP.NET, and I can get the listbox to show up, but not the individual items in the listbox. I'm testing it with a console.writeline command, to see if that outputs anything - but nothing is being put out on the ASP page.
I'm not certain how I should reference these particular sections (new to C#, asking like 3 dozen questions about this).
ASP code looks like this:
<asp:ListBox ID="listBox1" runat="server">
You have some confused declarations.
You declare a method called PeerReview, but you also have an attempt to create an instance of PeerReview as though it were a type. I think you really just want to call the PeerReview method from your button click event, eg
public void SaveBtn_Click(object sender, EventArgs e)
{
PeerReview();
}
And then eliminate the "PeerReview pr = new PeerReview();" line. Also, as this is on a page, you have an implicit reference within the partial class to the listbox by its ID, so you don't need to pass it as a parameter. And the Console.WriteLines are not useful in a web application - you might try Response.Write if you're wanting to add that to the output for debug purposes.
Edits based on OP response
You should call PeerReview in the Page_Load event handler:
public void Page_Load(object sender, EventArgs e)
{
// You need to determine if you should call PeerReview every time the page
// loads, or only on the initial call of the page, thus determining whether
// you need the IsPostBack() test. My instinct is that you *do* want to constrain
// it to the first pass, but only you can make that determination for
// certain based on your requirements.
if (!Page.IsPostBack) //Do you need this check?
{
PeerReview();
}
}
You're trying to add items to listbox though your listBox has an id of listBox1
Rather than looping through your data and adding items why not bind the datasource to your listbox and then set the DataTextField and DataValueField on your listbox.
So for example (typos may exist..sorry.. been a while since i wrote C#)
MySqlConnection con = new MySqlConnection("server=localhost;database=hourtracking;uid=username;password=password");
MySqlCommand cmd = new MySqlCommand("select first_name from employee where active_status=1", con);
con.Open();
MySqlDataReader r = cmd.ExecuteReader();
listBox1.DataSource = r;
listBox1.DataBind();
con.Close();
If you can't bind to the reader (can't remember..) then dump your results into a datatable first, then bind to the listBox1
DataTable dTable = New DataTable();
dTable.Load(reader);
listBox1.DataSource = dTable;
listBox1.DataBind();
in your asp, set the listBox fields like:
<asp:ListBox ID="listBox1" runat="server" DataTextField="first_name" DataValueField="first_name">
quick view here is you are adding items to listbox instead of listBox1
change:
listbox.Items.Add(new ListItem(Convert.ToString(r["first_name"]), Convert.ToString(r["first_name"])));
to:
listBox1.Items.Add(new ListItem(Convert.ToString(r["first_name"]), Convert.ToString(r["first_name"])));