Refining the Form’s Data Grid View

We had already set some general options for the data grid view, but now that we’ve dropped a data source into the data grid view and have some columns, let’s edit the columns.

The Data Grid View Column Editor

Let’s start with the first column, ID. We don’t need to change the ReadOnly status because the data grid view’s overall ReadOnly status has already been set to True, but we want the ID to be formatted to four digits with 0 as a placeholder, thus ID 1 would display as 0001. We figure we’ll never have 10,000 clients, and if we do, we’ll be using different software.

For the ID column, set the Width to 32 or some value lower than the default 100. I usually use eight pixels per character as a rule of thumb when using Segoe UI at 9 pt. Then pop open the cell style builder and set the Format property to 0000 — without quote marks.

The Cell Style Builder

Now let’s do the same for the date. Well, not the same, but similar. We want the date to look like this: MM/DD HH:MM, that is, two-digit month, followed by two-digit day of the month, then two-digit hour, followed by two-digit minutes. I know this is Americas-centric (not just the US but the whole of the Americas), and we’ll figure out how to make it work automatically in locales that place the day before the month later.

I’ve set the Date column to a width of 80. In a flash of inspiration, I have renamed the header text from “Date” to “Since,” that is, the date since the person has been our client. Makes more sense, right? Then, in the cell style builder, I set the Format property to MM/dd hh:mm, again without quote marks. I know the width of 80 is a little loose, so I also see the Alignment property to MiddleCenter, so it always looks aligned.

Ok, this done, we run the application, and oops, we get this.

Unexpected date formatting or lack thereof

The date is formatted incorrectly! Or wait… it’s actually not formatted at all. Check with SQLite Studio and you’ll see that the Date column is a Text column. What the heck? Then you remember that was a design choice made when the database was setup. SQLite doesn’t have a specific date type. You can store dates as text, real numbers, or integer numbers. Whatever choice you make, you must use SQL functions to retrieve and store values, and I don’t know how that’s going to work with the queries that Visual Studio generates automatically. (“I told you we should have gone with Access!”)

It turns out there’s a very useful data grid view event called CellFormatting. As the data grid view is being displayed, this event fires for every cell. It has an argument e that contains the row number, the column number, the cell value, etc. We can then change the cell value to display what we want. With the data grid selected, change the view in the Properties tab from properties to events, and double-click on CellFormatting. This will create the event method and open the editor. It’s empty, so we’ll have to add the necessary code..

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    var dgv = sender as DataGridView;
    if (e.ColumnIndex == dgv.Columns["Since"].Index)
    {
        DateTime dt = Convert.ToDateTime(e.Value);
        e.Value = dt.ToString("MM/dd hh:mm");
    }
}

In the code above, we start by creating a reference to the data grid view. You might ask, why not just refer to dataGridView1? This way is more foolproof. What if you had several data grid views, and referred to the wrong one? Ok, I’m sure you’d notice that right away, but still, it’s good practice.

Every time the event fires, we check to see if the current column is the “Since” column. You might ask, why not just refer to 1, which we know is the index number of the “Since” column. The reason we don’t is that the column might change. This way, it finds the column no matter where it is.

Once the current cell is the cell with the date, we create a DateTime object with the value converted from the string value in e. Then we convert the value back into string, this time with the format we want. It would have been possible to do it in one line, like this:

e.Value = Convert.ToDateTime(e.Value).ToString("MM/dd hh:mm");

And sure, it works, but you’re saving a line and windup up with a cryptic line of code the workings of which you won’t remember in six months. It’s just so much clearer when it’s like this:

 DateTime dt = Convert.ToDateTime(e.Value);
 e.Value = dt.ToString("MM/dd hh:mm");

Leave a Reply

Your email address will not be published. Required fields are marked *