I have a datagrid and a refresh button. I want to refresh data when I click on it but it won't. I also deleted all the rows from SQL Server but the data is still there.
Here's my button code:
Student std = new Student();
dataGridView1.DataSource = false;
dataGridView1.DataSource = std.List();
and here's is my List() function:
public DataTable List()
{
try
{
sdl.Command.CommandText = this.GetType().Name + "_List";
var dt = new DataTable();
dt.Clear();
SqlDataAdapter sda = new SqlDataAdapter(sdl.Command);
sda.Fill(dt);
return dt;
}
catch (Exception ex)
{
this.Message = ex.Message;
throw;
}
finally
{
if (sdl.Connection.State == System.Data.ConnectionState.Open)
{
sdl.Connection.Close();
}
}
}
I think you just need below line
dataGridView1.DataBind();
Assuming that you are using Windows Forms, to refresh the datagrid contents, assuming that std.List() works and actually gets new data you could try:
this.dataGridView1.EndEdit(); //end current edits if you allow this (optional)
this.dataGridView1.DataSource = null; //reset datasource binding
this.dataGridView1.DataSource = std.List();
This topic has been debated heavily in the past e.g. see:Refresh dgv.
DataSet ds = new DataSet();
ds.Tables.Add(List());
DataGridView1.DataSource = ds.Tables[0].DefaultView;
Related
We are developing application using WPF,material design and MS-Access 2007 as Back End. Now we are facing problem of application slow down while opening single view ,that particular view have 16 combo's which fill. It take 7 seconds for process, following code used for bind combo box item source
List<ComboBind> values = new List<ComboBind>();
try
{
using (var oleDbCommand = new OleDbCommand())
{
oleDbCommand.CommandText = query ;
oleDbCommand.Connection = Connection.con;
var sql = query;
var oleDbDataReader = oleDbCommand.ExecuteReader();
while (oleDbDataReader.Read())
{
ComboBind b = new ComboBind();
b.id = oleDbDataReader[0].ToString().ToInt();
b.name = oleDbDataReader[1].ToString();
values.Add(b);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
It looks like you are trying to load data in UI thread during view initialization and this is the reason of the issue. Either do loading of data in background thread or do it before opening the view.
Simple code snippet for loading data in separate task:
//Might be your view code behind or
//ViewModel if you are using MVVM
public class ViewCodeBehind
{
public List<ComboBind> ComboItems { get; set; }
public void Initialize()
{
//start bacground task for data loading
var comboQuery = "select *from data";
Task.Run(() => LoadItems(comboQuery));
}
public void LoadItems(string query)
{
List<ComboBind> values = new List<ComboBind>();
try
{
using (var oleDbCommand = new OleDbCommand())
{
oleDbCommand.CommandText = query;
oleDbCommand.Connection = Connection.con;
var sql = query;
var oleDbDataReader = oleDbCommand.ExecuteReader();
while (oleDbDataReader.Read())
{
ComboBind b = new ComboBind();
b.id = oleDbDataReader[0].ToString().ToInt();
b.name = oleDbDataReader[1].ToString();
values.Add(b);
}
}
//use dispatcher to pass data back to UI thread
System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke(
new Action(() =>
{
ComboItems = values;
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Im new to C#, so bear with me. Im using C#, a Form, and SQL Server 2012.
I have written some code that uses a Background Worker (from the form designer) and a progress bar to illustrate to the user the percentage of data that needs to be loaded from a SQL query until all records are completely read.
The problem Im having is that when the Worker is completed, I get many duplicate records listed in the datagridview. I should be getting only 14 returned records from my query, but I get many more (which are duplicates).
Im not sure why? Im sure there is a bug here (and that my beginnner code can be improved).
Can someone help my understand why Im getting duplicate records once the worker completes? My code is below
private void button2_Click(object sender, EventArgs e)
{
bgw.WorkerReportsProgress = true;
bgw.WorkerSupportsCancellation = false;
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
bgw.ProgressChanged += new ProgressChangedEventHandler(bgw_ProgressChanged);
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
System.Threading.Thread.Sleep(10);
bgw.RunWorkerAsync();
}
DataSet ds = new DataSet();
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
string query = "Select * from Stars_Pillars";
string connetionString = null;
SqlConnection cnn;
connetionString = "Server=xxx\\xxx;Initial Catalog=xxx;User ID=xxx;Password=xxx;";
cnn = new SqlConnection(connetionString);
SqlDataAdapter da = new SqlDataAdapter(query, cnn);
//DataSet ds = new DataSet();
try
{
cnn.Open();
int resda, startrow, pagesize, pageno;
pagesize = getRowCount();
progressBar1.Maximum = pagesize;
pageno = 1;
ds.Tables.Clear();
dataGridView1.Rows.Clear();
while (true)
{
if (!bgw.CancellationPending)
{
startrow = pageno;
resda = da.Fill(ds, startrow, pagesize, "Stars_Pillars");
if (resda == 0)
{
e.Cancel = true;
break;
}
else
{
System.Threading.Thread.Sleep(10);
int percents = (pageno * 100 / pagesize);
bgw.ReportProgress(percents, pageno);
pageno++;
}
}
else
{
e.Cancel = true;
break;
}
}
da.Dispose();
cnn.Close();
cnn.Dispose();
}
catch (Exception ex)
{
MessageBox.Show("Can not open connection ! ");
}
}
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.PerformStep();
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
progressBar1.Value = progressBar1.Maximum;
progressBar1.Visible = false;
dataGridView1.DataSource = ds.Tables[0];
}
private int getRowCount()
{
int count = 0;
string connetionString;
connetionString = "Server=xxxx\\xxxx;Initial Catalog=xxxx;User ID=xxxx;Password=xxxx;";
SqlConnection conn = new SqlConnection(connetionString);
string sql = "SELECT COUNT(Serial_Number) FROM [Stars_Pillars]";
SqlCommand cmd = new SqlCommand(sql, conn);
try
{
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
count = (int)dr[0];
}
}
catch { }
finally
{
conn.Close();
}
return count;
}
there is a lot of improvements to make in your code...you should never use while (true) it is extremely bad practice and you can end with infinite loop. also, there is no way to measure and show progress of filling a dataset with dataAdapter.
if the operation takes time show a Marquee style progress bar.
for start try this code to load data from database to the DataSet object:
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
try
{
string query = "Select * from Stars_Pillars";
connetionString = "Server=xxx\\xxx;Initial Catalog=xxx;User ID=xxx;Password=xxx;";
using(cnn = new SqlConnection(connetionString))
{
cnn.Open();
using(SqlDataAdapter da = new SqlDataAdapter(query, cnn))
{
adapter.Fill(ds);
cnn.Close();
}
}
} catch (Exception ex) {
// handle errors here and close connetion if its open
}
}
You must be getting an exception with your code.
You cannot access UI element from bgwDoWork()
The below line must be failing.
dataGridView1.Rows.Clear();
Please check.
My Combobox does not show me the values in my SQL-Attribute "TimeBlock", instead it shows System.Data.DataRow 5 Times. What is wrong with my code?
Code:
//DAL:
public class DAL{
string ConnectionString = "server=ICSSQL13\\Grupp28,1528; Trusted_Connection=yes; database=Yoloswag";
public DataTable StoreSqlDataInComboBoxTP()
{
SqlConnection Conn = new SqlConnection(ConnectionString);
Conn.Open();
string StoreSqlDataInComboBoxTP = "SELECT TimeBlock FROM TimePeriod GROUP BY TimeBlock";
SqlCommand Cmd = new SqlCommand(StoreSqlDataInComboBoxTP, Conn);
SqlDataAdapter Adapter = new SqlDataAdapter(Cmd);
DataSet DSet = new DataSet();
Adapter.Fill(DSet);
Adapter.Dispose();
Cmd.Dispose();
Conn.Close();
Conn.Close();
return DSet.Tables[0];
}
}
//Controller:
public class Controller
{
DAL Dal = new DAL();
public DataTable storesqldataincomboboxtp()
{
return Dal.StoreSqlDataInComboBoxTP();
}
}
//View:
public partial class Booking : Form
{
Controller controller = new Controller();
DataTable DTable = new DataTable();
DataSet DSet = new DataSet();
//Ignore string UserName
public Booking(string UserName){
DTable = controller.storesqldataincomboboxtp();
if (DTable.Rows.Count > 0)
{
for (int i = 0; i < DTable.Rows.Count; i++)
{
CBTime.Items.Add(DTable.Rows[i].ToString());
}
}
}
}
Instead of the 5 System.Data.DataRow I want to show what is stored in "TimeBlock".
"SELECT TimeBlock From TimePeriod GROUP BY TimeBlock" shows:
"08-00 - 10:00"
"10:00 - 12:00"
"12:00 - 14:00"
"14:00 - 16:00"
"16:00 - 18:00"
How can i solve this?
Thanks
You are not getting to the Field level when you are calling the Add() on CBTime. Something like this within your conditional checking that your table has rows would work:
foreach (DataRow dRow in DTable.Rows)
{
CBTime.Items.Add(dRow["TimeBlock"]);
}
I'm trying to get a "changed currentcell" event in DataGridView, but every time I try to load the form (which is a child of another form), I get an exception in the datagridview_currentcell event:
SystemNullReferenceException: object not set to an instance of an object.
I guess it's because I haven't selected any row. Of course I can use catch and try to bypass, but I want a more elegant way and to know what am I doing wrong.
Here's my code:
Form2.CS:
namespace AsefotSystem
{
public partial class ownerReport : Form
{
public ownerReport()
{
InitializeComponent();
loadDB();
setGrid();
}
private void loadDB()
{
string connetionString = null;
OleDbConnection connection;
OleDbDataAdapter oledbAdapter;
DataSet ds = new DataSet();
string sql2 = null;
connetionString = ConfigurationManager.ConnectionStrings["RiskDB"].ConnectionString;
sql2 = "select * From tbl2_asefot";
connection = new OleDbConnection(connetionString);
try
{
connection.Open();
oledbAdapter = new OleDbDataAdapter(sql2, connection);
oledbAdapter.Fill(ds, "Asefot");
oledbAdapter.Dispose();
connection.Close();
dsAsefotGrid = ds;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void setGrid()
{
Controls.Add(dataGridView1);
dataGridView1.DataSource = dsAsefotGrid.Tables[0];
}
private void dataGridView1_CurrentCell(object sender, EventArgs e)
{
try
{
textBox1.Text = dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[2].Value.ToString();
textBox2.Text = dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[1].Value.ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
DataSet dsAsefotGrid;
}
}
Form2.Designer.CS:
this.dataGridView1.CurrentCellChanged += new System.EventHandler(this.dataGridView1_CurrentCell);
Instead of the try{} catch{}, you could test if the CurrentCell or even CurrentRow is not null.
if(dataGridView1.CurrentCell != null)
{
textBox1.Text = dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[2].Value.ToString();
textBox2.Text = dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[1].Value.ToString();
}
Your dataGridView Cell has no value and you are trying to save a string of null.
Try catching the exception and inform the user that he has to write something in the cell
try
{
textBox1.Text = dataGridView1.Rows[dataGridView1.
CurrentRow.Index].Cells[2].Value.ToString();
}
catch(NullReferenceException)
{
MessageBox.Show("You cannot process an empty cell");
}
Please find more information under the following link:
net webdeveloper and usually don't make any win32 apps. but now i have to. i have a list with about 2000 entries.
each entry should be displayed as, a label with textbox another label and picture. i have made this with a flowlayoutpanel and i did a foreach on the entries to make a panel for each entry with the label, textbox, label and a picturebox.
now i have rendering issues when it comes above 1000 entries.
so i have read that i should use a listview or datagridview.
now i have a datagridview like this:
DataGridView dgv = new DataGridView();
dgv.AutoSize = true;
dgv.ScrollBars = ScrollBars.Vertical;
System.Data.DataTable dt = new System.Data.DataTable();
DataColumn dc1 = new DataColumn("Code", typeof(string));
dc1.ReadOnly = true;
dt.Columns.Add(dc1);
dt.Columns.Add(new DataColumn("Quantity", typeof(int)));
DataColumn dc3 = new DataColumn("Price", typeof(string));
dc3.ReadOnly = true;
dt.Columns.Add(dc3);
dt.Columns.Add(new DataColumn("Image", typeof(Bitmap)));
foreach (Product pd in products)
{
DataRow dr = dt.NewRow();
dr["Code"] = pd.ProductCode;
dr["Quantity"] = pd.ProductQuantity;
dr["Price"] = "€ " + String.Format("{0:0,00}", pd.ProductResalePrice.ToString());
dr["Image"] = BitmapFromWeb(pd.ProductImage);
dt.Rows.Add(dr);
}
dt.AcceptChanges();
dgv.RowTemplate.Height = 50;
dgv.DataSource = dt;
but the thing is that a bitmap on a datagridview is really slow! the picturebox option and panels which i had before where much faster. how do i resolve this?
the second question is: which event do i need when i want to track the changes made in the 2nd column?
ow one thing: the images are online available so the 'pd.ProductImage' is an url
private static Bitmap BitmapFromWeb(string URL)
{
try
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(URL);
myRequest.Method = "GET";
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(myResponse.GetResponseStream());
myResponse.Close();
return bmp;
}
catch (Exception ex)
{
return null; // if for some reason we couldn't get to image, we return null
}
}
Do the image load asyncrhonously then force a refresh of the cell. You can put your foreach code into a call to the ThreadPool, something like...
ThreadPool.QueueUserWorkItem(delegate
{
foreach (DataRow row in dt)
{
row["Image"] = BitmapFromWeb(Products[row["Code"]].ProductImage);
//maybe a call to invalidate here, remember to do Control.Invoke(...)
}
}
Edit: here is a sample code that I tested inside the Form constructor...
DataTable t= new DataTable();
t.Columns.Add("id");
t.Columns.Add("uri");
t.Columns.Add(new DataColumn("Img",typeof(Bitmap)));
Bitmap b = new Bitmap(50, 15);
using (Graphics g = Graphics.FromImage(b))
{
g.DrawString("Loading...", this.Font, new SolidBrush(Color.Black), 0f,0f);
}
t.Rows.Add(new object[] { "1", "http://farm1.static.flickr.com/88/377522544_c4774f15cc_s.jpg", b });
t.Rows.Add(new object[] { "2", "http://farm1.static.flickr.com/175/377522405_2c505def99_s.jpg", b });
t.Rows.Add(new object[] { "3", "http://farm1.static.flickr.com/185/377524902_72f82e2db9_s.jpg", b });
t.Rows.Add(new object[] { "4", "http://farm1.static.flickr.com/136/377524944_d011abf786_s.jpg", b });
t.Rows.Add(new object[] { "5", "http://farm1.static.flickr.com/137/377528675_d3b9d541fb_s.jpg", b });
dataGridView1.DataSource = t;
ThreadPool.QueueUserWorkItem(delegate
{
foreach (DataRow row in t.Rows)
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(row["uri"].ToString());
myRequest.Method = "GET";
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(myResponse.GetResponseStream());
myResponse.Close();
row["Img"] = bmp;
}
});
dataGridView1.CellEndEdit += dataGridView1_CellEndEdit;
.... and in the cell end edit code:
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
string value = dataGridView1.Rows[e.RowIndex].Cells["uri"].Value.ToString();
ThreadPool.QueueUserWorkItem(delegate
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(value);
myRequest.Method = "GET";
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(myResponse.GetResponseStream());
myResponse.Close();
dataGridView1.Rows[e.RowIndex].Cells["Img"].Value=bmp;
});
}
// table is DataTable object declared as member in my form class
table = new DataTable();
table.Columns.Add(new DataColumn("Column1", typeof(string)));
table.Columns.Add(new DataColumn("Column2", typeof(string)));
table.Columns.Add(new DataColumn("Column3", typeof(System.Drawing.Bitmap)));
dataGridView1.DataSource = table;