0

The idea here is that I redraw the combol "cell" so that it shows the block of colour and text. This is when form displays and it is about to show the dropdown:

Default rendering

After I have selected a colour it does weird:

Weird results

Now it is all wrong. I have to hover the mouse over the control to render other bits. Just not working right.

My handler:

    private void DataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        if(e.ColumnIndex == 0 && e.RowIndex > 0)
        {
            e.PaintBackground(e.ClipBounds, true);
            e.PaintContent(e.ClipBounds);

            Graphics g = e.Graphics;
            Color c = Color.Empty;
            string s = "";
            Brush br = SystemBrushes.WindowText;
            Brush brBack;
            Rectangle rDraw;

            rDraw = e.ClipBounds;
            rDraw.Inflate(-1, -1);

            {
                brBack = Brushes.White;
                g.FillRectangle(brBack, e.ClipBounds);
            }

            try
            {
                ComboboxColorItem oColorItem = (ComboboxColorItem)((ComboBox)sender).SelectedItem;
                s = oColorItem.ToString();
                c = oColorItem.Value;
            }
            catch
            {
                s = "red";
                c = Color.Red;
            }

            SolidBrush b = new SolidBrush(c);
            Rectangle r = new Rectangle(e.ClipBounds.Left + 5, e.ClipBounds.Top + 3, 10, 10);
            g.FillRectangle(b, r);
            g.DrawRectangle(Pens.Black, r);
            g.DrawString(s, Form.DefaultFont, Brushes.Black, e.ClipBounds.Left + 25, e.ClipBounds.Top + 1);

            b.Dispose();
            g.Dispose();

            e.Handled = true;
        }
    }
}

Is there something I am missing? Must be.

Update:

I tried this in the CellPainting event:

if(e.ColumnIndex == 0 && e.RowIndex > 0)
{
    using (Graphics g = e.Graphics)
    {
        g.FillRectangle(Brushes.Aqua, e.CellBounds);
    }

}
else
{
    e.PaintBackground(e.CellBounds, true);
    e.PaintContent(e.CellBounds);
}
e.Handled = true;

That improves things in the sense that it does not go as weird. Ofcourse, it is not actually drawing anything. But then it doe snot take long for the left most cells (with the editing symbols) to only show in white. So the mechanics of it are still not right. Thank you.

If I try it the way suggested I end up with:

Results

Made progress! Can we adkjust it to still include the grid lines? Like in normal cells?

Show gridlines

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
  • 1
    Definitely don't use ClipBounds. – LarsTech Jun 07 '16 at 16:24
  • @LarsTech, I got that from here: http://stackoverflow.com/questions/7482534/custom-draw-of-datagridviewcomboboxcolumn – Andrew Truckle Jun 07 '16 at 16:25
  • 1
    I'll have to revisit my answer. :-) – LarsTech Jun 07 '16 at 16:26
  • @LarsTech I tried CellBounds but I still get the sife effect of all the rest of the control doing doo-lally. As a side note, I also need to draw the dropdown combo arrow but was not sure how to do it based on the other question. – Andrew Truckle Jun 07 '16 at 16:27
  • One error seems to be that you are all over the cell. And after the content has been displayed. Move that line to the end first! Do you want to draw only the small rectangle or the cell background? Also: do look at the values of e.ClipBounds! surely not what you want! To color the Cell use e.Graphics.Clear(color).. – TaW Jun 07 '16 at 16:36
  • @TaW if I use e.Graphics.Clear(color) it fills the whole grid .... – Andrew Truckle Jun 07 '16 at 17:00
  • 1
    Yes, you are right. Sorry.. Please have a look at my answer; one serious mistake is deleting the Graphics object you didn't create; this is funny, but it seems the DGV is caching it while looping over the cells.. – TaW Jun 07 '16 at 17:03

1 Answers1

1

After

  • exchanging all ClipBounds by CellBounds
  • Deleting the g.Dispose();

..things look almost normal.

This is the result :

enter image description here

Of this Paint event:

private void dataGridView2_CellPainting(object sender, 
                                        DataGridViewCellPaintingEventArgs e)
{
    if (e.ColumnIndex == 4 && e.RowIndex == 0)  // use your own checks here!!
    {
        e.PaintBackground(e.CellBounds, true);
        e.PaintContent(e.CellBounds);

        Graphics g = e.Graphics;
        Color c = Color.Empty;
        string s = "";
        Brush br = SystemBrushes.WindowText;
        Brush brBack;
        Rectangle rDraw;

        rDraw = e.CellBounds;
        rDraw.Inflate(-1, -1);

        {
            brBack = Brushes.White;
            g.FillRectangle(brBack, rDraw);  // **
        }

        try
        {    // use your own code here again!
            //  ComboboxColorItem oColorItem = 
            //      (ComboboxColorItem)((ComboBox)sender).SelectedItem;
            s = "WW";// oColorItem.ToString();
            c = Color.LawnGreen;// oColorItem.Value;
        } catch
        {
            s = "red";
            c = Color.Red;
        }

        // asuming a square is right; make it a few pixels smaller!
        int butSize = e.CellBounds.Height;  
        Rectangle rbut = new Rectangle(e.CellBounds.Right - butSize , 
                                       e.CellBounds.Top, butSize , butSize );
        ComboBoxRenderer.DrawDropDownButton(e.Graphics, rbut,  
                   System.Windows.Forms.VisualStyles.ComboBoxState.Normal);


        SolidBrush b = new SolidBrush(c);
        Rectangle r = new Rectangle( e.CellBounds.Left + 5, 
                                     e.CellBounds.Top + 3, 10, 10);
        g.FillRectangle(b, r);
        g.DrawRectangle(Pens.Black, r);
        g.DrawString(s, Form.DefaultFont, Brushes.Black, 
                     e.CellBounds.Left + 25, e.CellBounds.Top + 1);

        b.Dispose();
        //g.Dispose();  <-- do not dispose of thing you have not created!

        e.Handled = true;
    }

}

Note that I only have one CombBoxCell, so I changed the checks. And that I have no ComboboxColorItem, so I substituted a random string & color.

Update from OP: I had some of the syntax wrong and needed:

// use your own code here again!
if(DataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
{
    ComboboxColorItem oColorItem = (ComboboxColorItem)DataGridView1
                                  .Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
    s = oColorItem.ToString();
    c = oColorItem.Value;
}
TaW
  • 53,122
  • 8
  • 69
  • 111
  • The combo box itself draws fine. I just want the cell (when not being edited) to have the block of colour and text drop arrow. – Andrew Truckle Jun 07 '16 at 17:02
  • Can I please see your version of the handler because mine is still wrong. – Andrew Truckle Jun 07 '16 at 17:04
  • Thanks for giving more info. Please see my updated question. I get different results. – Andrew Truckle Jun 07 '16 at 17:16
  • 1
    @AndrewTruckle You only set `e.Handled = true;` for the cells you want painted. – LarsTech Jun 07 '16 at 17:19
  • I have added the arrow using the ComboBoxRenderer @Lars, right, as usual. – TaW Jun 07 '16 at 17:23
  • Thanks. I had to remove the Clear call. Now it is better. But I think I still have an issue. It seems that it must not be an actual "combo" at the point we are painting because it alwats goes to the catch statement and does red. – Andrew Truckle Jun 07 '16 at 17:25
  • Whoops, the clear was a leftover. Yes, whaen we are paint there may indeed be no selected item. Not sure atm how to handle that, but it should be possible by digging a little into the cell's items and comparing them to the cell value.. – TaW Jun 07 '16 at 17:29
  • My code was wrong as you will see from my edit to your answer. On top of that I have modified the original question about gridlines. – Andrew Truckle Jun 07 '16 at 17:38
  • @AndrewTruckle That's not going to work. You will have to set the DataSource of the grid's combobox to a list of your class items, then set the DisplayMember and ValueMember properties. Once you do that, then you can access your information through the cell's FormattedValue and Value properties, just cast appropriately. – LarsTech Jun 07 '16 at 17:46
  • 1
    The `FillRectangle` shouldn't use the `CellBound` but the `rDraw` you have prepared so nicely.. (**) – TaW Jun 07 '16 at 17:51
  • @LarsTech For what you are saying, it may apply to: http://stackoverflow.com/questions/37674726/using-a-custom-combo-with-a-data-grid-view-and-datasource – Andrew Truckle Jun 07 '16 at 18:02