48

I have a DataGridView bound to a DataTable. The DataTable is populated from a database query. The table contains a column named BestBefore. BestBefore is a date formatted as a string (SQLite doesn't have date types).

I would like to programmatically add a new column to the DataGridView called Status. If BestBefore is less than the current date, Status value should be set to OK, otherwise Status value should be set to NOT OK.

I'm very new to Winforms, so some example code would be greatly appreciated.

UPDATE:

I think DataColumn.Expression is okay for doing simple calculations such multiplying a column's integer value by another value, but what about doing what I need to do? That is, calculate the difference between now and the date (string formatted) in the BestBefore column to determine what value to give the new status column. Example code would be appreciated.

3 Answers 3

50

Keep it simple

dataGridView1.Columns.Add("newColumnName", "Column Name in Text");

To add rows

dataGridView1.Rows.Add("Value for column#1"); // [,"column 2",...]
25

Add new column to DataTable and use column Expression property to set your Status expression.

Here you can find good example: DataColumn.Expression Property

DataTable and DataColumn Expressions in ADO.NET - Calculated Columns

UPDATE

Code sample:

DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("colBestBefore", typeof(DateTime)));
dt.Columns.Add(new DataColumn("colStatus", typeof(string)));

dt.Columns["colStatus"].Expression = String.Format("IIF(colBestBefore < #{0}#, 'Ok','Not ok')", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

dt.Rows.Add(DateTime.Now.AddDays(-1));
dt.Rows.Add(DateTime.Now.AddDays(1));
dt.Rows.Add(DateTime.Now.AddDays(2));
dt.Rows.Add(DateTime.Now.AddDays(-2));

demoGridView.DataSource = dt;

UPDATE #2

dt.Columns["colStatus"].Expression = String.Format("IIF(CONVERT(colBestBefore, 'System.DateTime') < #{0}#, 'Ok','Not ok')", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
4
  • That's okay for simple expressions, but what about doing what I need to do? That is, calculate the difference between now and the date (string formatted) in the BestBefore column to determine what value to give the new status column. Example code would be appreciated. Thanks.
    – halfpint
    Commented Apr 3, 2011 at 6:17
  • @halfpint: i updated my answer with working sample of what you need.
    – HABJAN
    Commented Apr 3, 2011 at 8:11
  • My BestBefore column is a string formatted date and time not a DateTime type. Can this still be made to work? Thank you for your feedback - much appreciated.
    – halfpint
    Commented Apr 3, 2011 at 14:57
  • @halfpint: yep, take a look at UPDATE #2.
    – HABJAN
    Commented Apr 3, 2011 at 21:25
19

Here's a sample method that adds two extra columns programmatically to the grid view:

    private void AddColumnsProgrammatically()
    {
        // I created these columns at function scope but if you want to access 
        // easily from other parts of your class, just move them to class scope.
        // E.g. Declare them outside of the function...
        var col3 = new DataGridViewTextBoxColumn();
        var col4 = new DataGridViewCheckBoxColumn();

        col3.HeaderText = "Column3";
        col3.Name = "Column3";

        col4.HeaderText = "Column4";
        col4.Name = "Column4";

        dataGridView1.Columns.AddRange(new DataGridViewColumn[] {col3,col4});
    }

A great way to figure out how to do this kind of process is to create a form, add a grid view control and add some columns. (This process will actually work for ANY kind of form control. All instantiation and initialization happens in the Designer.) Then examine the form's Designer.cs file to see how the construction takes place. (Visual Studio does everything programmatically but hides it in the Form Designer.)

For this example I created two columns for the view named Column1 and Column2 and then searched Form1.Designer.cs for Column1 to see everywhere it was referenced. The following information is what I gleaned and, copied and modified to create two more columns dynamically:

// Note that this info scattered throughout the designer but can easily collected.

        System.Windows.Forms.DataGridViewTextBoxColumn Column1;
        System.Windows.Forms.DataGridViewCheckBoxColumn Column2;

        this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
        this.Column2 = new System.Windows.Forms.DataGridViewCheckBoxColumn();

        this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
        this.Column1,
        this.Column2});

        this.Column1.HeaderText = "Column1";
        this.Column1.Name = "Column1";

        this.Column2.HeaderText = "Column2";
        this.Column2.Name = "Column2";
5
  • I don't want to just add a column. I want to set its value based on the value of another column with a date value.
    – halfpint
    Commented Apr 2, 2011 at 18:56
  • after you add the column, in the DataBindingComplete event do something like this: foreach (DataGridViewRow row in dgv.Rows) {if (row.Cells[7].Value.ToString()=="1") row.Cells[0].Value = "number one"; } (just an example..). But remember IT HAS to be in the DataBindingComplete, otherwise it'll remain blank
    – BornToCode
    Commented Oct 22, 2012 at 20:57
  • 1
    I like this answer because it doesn't need the additional DataTable defined. This is the most clean and concise answer to solving this problem. If I could award more than 1 vote I would. Great answer... Commented Dec 7, 2014 at 21:00
  • +1 awesome! thanks for teaching me how to fish. The technique will be useful for learning many things about winforms Commented Jul 12, 2016 at 19:17
  • @JohnHenckel n/p That's what SO is all about. Also, thanks for the kind feedback!
    – Paul Sasik
    Commented Jul 13, 2016 at 6:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.