简体   繁体   中英

Changing the cell background color of a 'DataGridView' in virtual mode

I am just learning how to use a DataGridView control in virtual mode. I'm using a list array to store the contents of a text file that could be small or quite large. One particular column in the DataGridView needs to have the background color of the cell changed based on the text content in that cell. So, I have an event handler:

private void datagridview_CellValueNeeded(
    object sender, DataGridViewCellValueEventArgs e)

that populates each row of the DataGridView . My problem is that I don't know where to insert the code to set the background color as the cells are created in each row (now in virtual mode).

I tried using an event handler for CellValueNeeded to first check for a particular column ID and then setting the cell background color as follows:

datagridview[e.ColumnIndex, e.RowIndex].Style.SelectionBackColor =
    component_color;

where component_color was predetermined. However, this approach didn't change the color. I also tried handling other events such as CellEnter , CellLeave , CellValueChanged , RowsAdded and RowLeave . However, I learned from my debugging effort that these events either never fire or fire before the CellValueNeeded event.

So, is it possible to set the background color of a cell as it is created in a particular column by handling the CellValueNeeded event? Or should I accomplish this by handling a different event?

You need to handle the DataGridView.CellFormatting event. For example:

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.ColumnIndex == 3 && e.Value == targetValue)
        e.CellStyle.BackColor = Color.Red;
    else
        e.CellStyle.BackColor = SystemColors.Window;
}

Cheers

Despite Luc answer is formally correct and would work in all scenarios, it is worth noting that assigning single properties on CellStyle property will Clone() the full original inherited style.

The best practices suggested by Microsoft and the hierarchy detailed explanation clearly state (and explain why) DataGridViewCellStyle should be reused whenever possible.

The trick is that since CellStyle contains the inherited style, you cannot directly change it, thus it has to be cloned before accessing it. If you have 1000 cells that match "target", then you clone 1000 time the same inherited style just to apply 1000 time the same one (with red back color). So the best practice says: set the column default to the expected default style for that column, then create the "highlight" cell style once and reuse it when possible.

In almost all scenarios the difference will not be noted and no penalty of any kind (memory, cpu, flickering, etc...) would be noted. Nevertheless, I believe it is important to understand that under the hood a lot of stuff is going on. Moreover, CellFormatting is called very often so it's very important to keep the underlying operations very quick in order to avoid side effects.

The above answer could also be rewritten this way:

private static DataGridViewCellStyle m_targetValueCellStyle = new DataGridViewCellStyle{ BackColor = Color.Red};

// Somewhere (i.e. in the constructor after InitializeComponents() ) set:
// dataGridView1.Columns[3].DefaultCellStyle = new DataGridViewCellStyle{ BackColor = SystemColors.Window};

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.ColumnIndex == 3 && e.Value == targetValue)
        e.CellStyle = m_targetValueCellStyle;
}

This approach can be quite limited in very complex scenarios because you need to know all styles and combination beforehand (eg red back color, white fore color but also red back color, black fore color and bold) and that may be tricky and cumbersome. I thought it would have been worth mentioning anyway what Microsoft suggests. It's not a matter of pure performance here, it's more a matter of know what you are doing and what is happening in order to pick the best (where what is best depends on the scenario) strategy. I believe we need to teach young programmers to make informed choices when developing.

Please consider my answer not alternative, yet complementary to Luc's one.

A

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM