It’s not often that I get the opportunity to blog about something neat that I learned to do in winforms so you know I gotta, even tho it’s not totally complete yet. Here’s how I got a DataGridViewButtonColumn to act as a color picker.

After a little bit of webernettin’, I found a post by Ward Bekker that describes how to handle the button click event of a DataGridViewButtonColumn. Sweet. We’ll get back to that code in a second.

I want to have a special button that will display a rectangle of the selected color, so I created a class that derives from DataGridViewButtonCell. I want to be able to set the Color of the rectangle, and of course we have to paint the rectangle so we’ll add a Color property of type Color (imagine that:) and override the Paint method.

public ColorPickerCell : DataGridViewButtonCell{
  const float phi = 1.618f;
  private Color colorValue;
  public Color Color {
    get { return colorValue; }
    set {  
      colorValue = value; 
      this.Value = value.ToArgb().ToString();
    }
  }

  protected override void Paint(Graphics graphics, 
    Rectangle clipBounds,
    Rectangle cellBounds, 
    int rowIndex, 
    DataGridViewElementStates cellState,
    object value, 
    object formattedValue, 
    string errorText, 
    DataGridViewCellStyle cellStyle, 
    DataGridViewAdvancedBorderStyle advancedBorderStyle, 
    DataGridViewPaintParts paintParts){
      //CDF: draw the button
      base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value,     formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
      //CDF: draw a purty rectangle over the button
      using(Pen darkPen = new Pen(SystemColors.ControlDark){
        Rectangle rc = new Rectangle(cellBounds.X + 8, cellBounds.Y + 3, 
        cellBounds.Width - (int)(cellBounds.Width * phi / 8), 
        cellBounds.Height - (int)(cellBounds.Height * phi / 4));

        graphics.FillRectangle(new SolidBrush(Color.FromArgb(int.Parse(formattedValue.ToString()))), rc);
        graphics.DrawRectangle(darkPen, rc);
      }
    }
  }

I also derived a class from DataGridViewButtonColumn (ColorPickerColumn), but I didn’t really override anything. Anyway, now that we’ve got a button that will display a colored rectangle, we can add a ColorPickerColumn to a DataGridView on a Form. The next step is to handle the CellContentClick event as Ward indicated.

private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) {
  //CDF: make sure we're on the right column. I used the name for this test.
  if(dataGridView1.Columns[e.ColumnIndex].Name == "ColorColumn"){
    ColorDialog dlg = new ColorDialog();
    ColorPickerCell currentCell = dataGridView1[e.ColumnIndex, e.RowIndex] as ColorPickerCell;

    if(dlg.ShowDialog() == DialogResult.OK){
      if(currentCell != null){
        currentCell.Color = dlg.Color;
        this.Invalidate();
      }
    }
  }

Seems to do exactly what I want for now. Nice XD