0
votes

The following code is designed to setup a DataGridView object in c# .net. It will populate the object and set the 'Selected Cell' fore/back colour to transparent. When a particular row is double clicked, if that row is not set, it should change the background colour to green. If that row is set, it should change the background colour to white.

two problems arise:

1) Initially the first row of the datagrid is highlighted. it is not transparent but solid white. Clicking a different row will fix this and the next selected row is transparent.

2) When a double click has been performed, the datagrid does not change the background of that row to its new colour. It will not change colour unless another row is selected.

I want the background colour change to be instant on the double click operation.

I also want the initial selected row to be transparent.

Can my code be fixed, or is there a better method to attain the desired effect.

Below is a simplified extract of my code.

Create a c# .net project, blank form.

Create a DataGridView object - do not set any parameters via the properties page. Use the following function to be called in the form constructor to setup the table:

const int TotalDummyData = 20;

/// <summary>
/// 
/// </summary>
private void CreateDGV()
{
    dgv.Width = 420;
    dgv.Columns.Add("h1", "Name");
    dgv.Columns.Add("h2", "Value");
    dgv.Columns[0].Width = 200;
    dgv.Columns[1].Width = 200;
    dgv.Columns[0].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
    dgv.Columns[1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
    dgv.Columns[0].SortMode = DataGridViewColumnSortMode.NotSortable;
    dgv.Columns[1].SortMode = DataGridViewColumnSortMode.NotSortable;

    for (int i = 0; i < TotalDummyData; i++)
    {
        DataGridViewRow dgvRow = new DataGridViewRow();
        DataGridViewCell dgvCell1 = new DataGridViewTextBoxCell();
        DataGridViewCell dgvCell2 = new DataGridViewTextBoxCell();
        dgvCell1.Value = "dummy_data_name_" + i.ToString();
        dgvCell2.Value = "dummy_data_value_" + i.ToString();
        dgvRow.Cells.Add(dgvCell1);
        dgvRow.Cells.Add(dgvCell2);
        dgv.Rows.Add(dgvRow);
    }
    dgv.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
    dgv.ColumnHeadersDefaultCellStyle.Font = new Font("Arial", 12.0f, FontStyle.Bold);
    dgv.AllowUserToAddRows = false;
    dgv.AllowUserToDeleteRows = false;
    dgv.AllowUserToResizeColumns = false;
    dgv.AllowUserToResizeRows = false;
    dgv.ReadOnly = true;
    dgv.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;
    dgv.RowHeadersVisible = false;
    dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
    dgv.DefaultCellStyle.SelectionBackColor = Color.Transparent;
    dgv.DefaultCellStyle.SelectionForeColor = Color.Transparent;
    dgv.CellMouseDoubleClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.dgv_CellContentDoubleClick);
}

Now create the cell double click function - this will change the cell background colour

bool[] DummyDataSet = new bool[20];

/// <summary>
/// 
/// </summary>
/// <param name ="sender"></param>
/// <param name ="e"></param>
private void dgv_CellContentDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
{
    if(!DummyDataSet[e.RowIndex])
    {
        DummyDataSet[e.RowIndex] = true;
        dgv.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.LightGreen;
    }
    else
    {
        DummyDataSet[e.RowIndex] = false;
        dgv.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.White;
    }
}
3

3 Answers

0
votes

If you're working in windows forms my understanding is that windows forms does not support true transparency. In other words, if you have an image or something behind your datagridview and a cell is "transparent" it won't show the part of the image behind it. Instead, it inherits its background color from the background color of the parent container. That's my understanding. I'm not familiar with WPF and transparency but maybe someone else is. Also, in your double click event handler you're using Color.White not Color.Transparent (but like I explained above, Color.Transparent is not true transparency anyways).

Also, you should try using the event CellDoubleClick instead of CellContentDoubleClick. Otherwise the user has to click the cell to "get into" the contents, then double-click the contents.

0
votes

For the answer as to why it changes color after you click another row, the problem is that after you double-click a row, it's still selected, so the datagridview default selection style of Color.Transparent still applies, and like I said, it's not true transparency, anyways. After you change the default cell style backcolor to green in your event handler, add this line: dgv.ClearSelection(); Then it will be colored immediately after you double-click.

EDIT: To address issue number 1 This one is a little trickier and kind of hackish, but the reason this is happening is because when the datagridview is drawn it sets the first row or cell or column as the current selection, depending on the dgv selection mode. Again, because you set the selection style back- and fore-colors to Color.Transparent (which actually will just end up being white for reasons already discussed) the first row is selected when the control is drawn and that's why you're getting all white. Unfortunately you can't clear the selection in your CreatedataGridView() method before the dgv is drawn, you need to clear the selection after the control is drawn. I accomplished this by adding two lines in your Form1() (or the form's Main()) method:

public Form1()
    {
        InitializeComponent();
        CreatedataGridView1();

        //Force the form and its children to be drawn...
        this.Show();

        //Now clear the selection
        dataGridView1.ClearSelection();
    }
0
votes

I've had this same problem, but I came up with what I think is a much simpler solution. Simply set the cell's 'SelectionBackColor' property to the same color as the desired cell background color, move the datagridview's focus temporarily to another cell, and then set it back to the cell under consideration. This (I believe) allows all the updating and repainting machinery to operate correctly. Here's my double-click event handler

       private void dataGridView_Types_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
    {
        DataGridView view = (DataGridView)sender;

        if (view.Columns[e.ColumnIndex].Name == "TypeTable_Color")
        {
            ColorDialog dlg = new ColorDialog();
            DialogResult res = dlg.ShowDialog();
            if (res == DialogResult.OK)
            {
                DataGridViewCell cell = view[e.ColumnIndex, e.RowIndex];
                cell.Style.BackColor = dlg.Color;
                cell.Style.SelectionBackColor = dlg.Color;
                view.CurrentCell = view.FirstDisplayedCell; \\temporarily move focus
                view.CurrentCell = view[e.ColumnIndex, e.RowIndex]; \\put it back - this updates selectionbackcolor
            }
        }
    }