Cathy
Cathy

Reputation: 1

C# timer event to update datagridview

I am trying to create a "dashboard" form with a text box and datagridview. The data loaded into them comes from an excel spreadsheet that is updated every 10 minutes. I added a timer to refresh the data but can't get the textbox and the datagridview on the form to update. I can tell the timer is working because the form WILL update if I scroll down to the bottom of the datagridview. What am I missing?

        public AllOrders()
    {
        InitializeComponent();
        System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
        timer1.Interval = 10000;
        timer1.Tick += new System.EventHandler(timer1_Tick);
        timer1.Enabled = true;
        timer1.Start();
        Get_Data();
    }
    private void Get_Data()
    {
        // connect to get file
        string ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source='\\\\xxxxx\\labdash.xls';Extended Properties=\"Excel 8.0;HDR=Yes\";";
        OleDbConnection MyConnection = new OleDbConnection(ConnectionString);
        // select only worksheet in spreadsheet
        OleDbDataAdapter myDataAdapter = new OleDbDataAdapter("select * from [Sheet1$]", MyConnection);
        // define dataset as entire spreadsheet
        DataSet ds = new DataSet();
        myDataAdapter.Fill(ds);
        // define view to set filters, restrictions, etc
        DataView dv;
        dv = new DataView(ds.Tables[0], "ordept = 'CHE'", "ordept", DataViewRowState.CurrentRows);
        dataGridView1.DataSource = dv;
        // define header information
        ctr = dataGridView1.Rows.Count;
        textBox1.Text = ctr.ToString() + "  outstanding tests";
        upddte = dataGridView1.Rows[1].Cells[14].Value.ToString();
        updtim = dataGridView1.Rows[1].Cells[15].Value.ToString();
        textBox2.Text = upddte.Substring(5, 2) + "  last updated";
        // hide columns not needed
        dataGridView1.Columns[0].Visible = false;
        dataGridView1.Columns[4].Visible = false;
        dataGridView1.Columns[5].Visible = false;
        dataGridView1.Columns[6].Visible = false;
        dataGridView1.Columns[9].Visible = false;
        dataGridView1.Columns[10].Visible = false;
        dataGridView1.Columns[11].Visible = false;
        dataGridView1.Columns[14].Visible = false;
        dataGridView1.Columns[15].Visible = false;
        dataGridView1.Columns[17].Visible = false;
        // sort by priority, specimen date, specimen time
        dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Ascending);
        dataGridView1.Sort(dataGridView1.Columns[13], ListSortDirection.Ascending);
        dataGridView1.Sort(dataGridView1.Columns[14], ListSortDirection.Ascending);
        // change font color for certain status'
        dataGridView1.RowPrePaint
            += new System.Windows.Forms.DataGridViewRowPrePaintEventHandler(dataGridView1_RowPrePaint);
        dataGridView1.Update();
        dataGridView1.Refresh();
        textBox1.Update();
        textBox1.Refresh();
        textBox2.Update();
        textBox2.Refresh();
    }
    private void timer1_Tick(object sender, EventArgs e)
    {
        Get_Data();
    }

Upvotes: 0

Views: 992

Answers (2)

Harald Coppoolse
Harald Coppoolse

Reputation: 30454

Apparently your form class is named AllOrders. The constructor:

public AllOrders()
{
    InitializeComponent();
    System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
    ...
}

What happens to timer1 at the end of your constructor? Is there anyone who holds a reference to the timer object? What will the garbage collector do?

Your Timer is a Component. Your Form can contain many Components, but you must keep them alive until you are certain that you don't need them anymore. The Timer is also IDisposable, you should Dispose it when your form is Disposed.

The easy way for any Component to do this, is to add the Component to your Form.Components. See the code of your Form Dispose, just above your Form's InitializeComponent.

You can add the Timer using your visual studio designer. It's in the Toolbox under Components. If you want to add it manually, make sure that it stays alive after the constructor, and add it to this.Components, so you know that it will be disposed when your form is disposed.

class Allorders : Form
{
    private readonly Timer timer1;

    public AllOrders()
    {
        InitializeComponent();
        this.timer1 = new Timer();
        this.components.Add(this.timer1);
        ... // other timer initializations
    }
}

The code to Dispose this.components is already in your form.Dispose Depending on what other conrols you have added to your form, this.components is null. In that case you must create it yourself:

InitializeComponent();

if (this.components == null)
    this.components = new System.ComponentModel.Container();
this.timer1 = new Timer();
this.components.Add(this.timer1);

Upvotes: 1

LarsTech
LarsTech

Reputation: 81610

You are adding a paint event on every tick of the timer. That calls multiple paint events and slows everything down, especially when you are scrolling.

Move the paint subscription to the constructor. Also, declare the timer at the form level so it can be properly disposed when the form closes.

System.Windows.Forms.Timer timer1;

public AllOrders()
{
  InitializeComponent();
  dataGridView1.RowPrePaint += dataGridView1_RowPrePaint;

  timer1 = new System.Windows.Forms.Timer();
  timer1.Interval = 10000;
  timer1.Tick += timer1_Tick;
  timer1.Start();
}

Upvotes: 0

Related Questions