12

i have a data gridview with 4 columns first 2 columns are combobox columns, third column is textbox column and 4th column is button column.In form load i have to disable the entire button column of datagrid and after this i should select first three columns and save these first three columns in database after saving this the button column in the particular row should enable.first three columns should be saved in databese by clicking a button. Please help me im struck up with this problem from many days here is the code which i used

private void SATAddTemplate_Load(object sender, EventArgs e)
{
           foreach (DataGridViewRow row in datagrdADDTEMP.Rows)
           {

               DataGridViewButtonCell btn = (DataGridViewButtonCell)row.Cells[3];
               btn.ReadOnly = true;
           }
}
 private void btnSaveSettings_Click(object sender, EventArgs e)
     {
           foreach (DataGridViewRow row in datagrdADDTEMP.Rows)
           {

               DataGridViewButtonCell btn = (DataGridViewButtonCell)row.Cells[3];
               btn.ReadOnly = false;
           }
     }
Jay Riggs
  • 53,046
  • 9
  • 139
  • 151
sree
  • 601
  • 5
  • 12
  • 33

4 Answers4

21

Here's some help with the problem of setting the Enabled property of the Buttons that appear in a DataGridViewButtonColumn.

You'll need to extend DataGridViewButtonColumn to create your own DataGridView column with disable-able buttons. This article on MSDN details how to do this.

The article has a lot of code, and I encourage you to take a close look, but all you really need to do is copy and paste into your project the following classes found in the article:
-- DataGridViewDisableButtonColumn
-- DataGridViewDisableButtonCell

Once you do this you will be able to add DataGridViewDisableButtonColumns to your DataGridView. Use the public Enabled property exposed in your custom column to set the Enabled property of each cell's Button control. Since you want to set the Enabled property of all the Buttons in the column you can write a helper method that loops through all rows in your DataGridView and sets the Enabled property:

private void SetDGVButtonColumnEnable(bool enabled) {
    foreach (DataGridViewRow row in dataGridView1.Rows) {
        // Set Enabled property of the fourth column in the DGV.
        ((DataGridViewDisableButtonCell)row.Cells[3]).Enabled = enabled;
    }
    dataGridView1.Refresh();
}
Jay Riggs
  • 53,046
  • 9
  • 139
  • 151
  • 12
    Why isn't the ability to disable a button in there by default I wonder? – Paul C Jan 18 '13 at 16:22
  • 2
    The `DataGridViewDisableButtonCell.Paint()` method in the MSDN article flickers on repaints (no double buffering). To remedy modify their implementation using [this article](https://msdn.microsoft.com/en-us/library/ka0yazs1(v=vs.110).aspx) as a guide. Create a BufferedGraphics object (e.g. `myBuffer`), replace usages of `graphics` with `myBuffer.Graphics`, and then call `myBuffer.Render()` at the end. Caveat: The call to `TextRenderer.DrawText()` MUST specify these text format flags to position the button text properly: `PreserveGraphicsTranslateTransform | HorizontalCenter | VerticalCenter` – Chris Staley Apr 13 '15 at 15:44
  • The solution in this link also doesn't cater for Padding in your CellStyle. You can alter the Paint Method to incorporate any Padding present in the "cellStyle" by adding the Padding.Horizontal value to buttonAdjustment.Width, and Padding.Vertical value to buttonAdjustment.Height and adding cellStyle's Padding.Left to buttonAdjustment.X and cellStyle's Padding.Top to buttonAdjustment.Y. – Stuart Helwig Apr 27 '15 at 03:12
  • @ChrisStaley I know this is a bit old question, but could You share code to flickering issue? I can't get this to work. – Misiu Feb 03 '16 at 12:01
  • @ChrisStaley thank You for this. I'll check that right away! – Misiu Feb 04 '16 at 15:02
15

This is a supplement to Jay's answer.

By request, here is the code that I used to create a button cell that could be disabled. It includes double-buffering so that the buttons do not flicker when the user scrolls.

/// <summary>
/// Adapted from https://msdn.microsoft.com/en-us/library/ms171619.aspx. Double-buffering was added to remove flicker on re-paints.
/// </summary>
public class DataGridViewDisableButtonCell : DataGridViewButtonCell
{
    private bool enabledValue;

    public bool Enabled
    {
        get { return enabledValue; }
        set
        {
            if (enabledValue == value) return;
            enabledValue = value;
            // force the cell to be re-painted
            if (DataGridView != null) DataGridView.InvalidateCell(this);
        }
    }

    // Override the Clone method so that the Enabled property is copied. 
    public override object Clone()
    {
        var cell = (DataGridViewDisableButtonCell) base.Clone();
        cell.Enabled = Enabled;
        return cell;
    }

    // By default, enable the button cell. 
    public DataGridViewDisableButtonCell()
    {
        enabledValue = true;
    }

    protected override void Paint(
        Graphics graphics,
        Rectangle clipBounds,
        Rectangle cellBounds,
        int rowIndex,
        DataGridViewElementStates elementState,
        object value,
        object formattedValue,
        string errorText,
        DataGridViewCellStyle cellStyle,
        DataGridViewAdvancedBorderStyle advancedBorderStyle,
        DataGridViewPaintParts paintParts)
    {
        // The button cell is disabled, so paint the border, background, and disabled button for the cell. 
        if (!enabledValue)
        {
            var currentContext = BufferedGraphicsManager.Current;

            using (var myBuffer = currentContext.Allocate(graphics, cellBounds))
            {
                // Draw the cell background, if specified. 
                if ((paintParts & DataGridViewPaintParts.Background) == DataGridViewPaintParts.Background)
                {
                    using (var cellBackground = new SolidBrush(cellStyle.BackColor))
                    {
                        myBuffer.Graphics.FillRectangle(cellBackground, cellBounds);
                    }
                }

                // Draw the cell borders, if specified. 
                if ((paintParts & DataGridViewPaintParts.Border) == DataGridViewPaintParts.Border)
                {
                    PaintBorder(myBuffer.Graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle);
                }

                // Calculate the area in which to draw the button.
                var buttonArea = cellBounds;
                var buttonAdjustment = BorderWidths(advancedBorderStyle);
                buttonArea.X += buttonAdjustment.X;
                buttonArea.Y += buttonAdjustment.Y;
                buttonArea.Height -= buttonAdjustment.Height;
                buttonArea.Width -= buttonAdjustment.Width;

                // Draw the disabled button.                
                ButtonRenderer.DrawButton(myBuffer.Graphics, buttonArea, PushButtonState.Disabled);

                // Draw the disabled button text.  
                var formattedValueString = FormattedValue as string;
                if (formattedValueString != null)
                {
                    TextRenderer.DrawText(myBuffer.Graphics, formattedValueString, DataGridView.Font, buttonArea, SystemColors.GrayText, TextFormatFlags.PreserveGraphicsTranslateTransform | TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);
                }

                myBuffer.Render();
            }
        }
        else
        {
            // The button cell is enabled, so let the base class handle the painting. 
            base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
        }
    }
}
Chris Staley
  • 2,370
  • 1
  • 20
  • 21
3

You can use this MSDN article MSDN article:Disable button in dataGridView it uses a class for datagridview button and notice that you have to check enable status of button whenever you willing to handle it

Hamid
  • 817
  • 1
  • 13
  • 29
0

I have two adjustments to @Chris Staley's answer (and therefore @Jay Riggs's answer).

1: If the SelectionMode is FullRowSelect of the DataGridView, you can add the following code to show the highlight of the selected row in the button cell:

// Draw the cell background, if specified.
if ((paintParts & DataGridViewPaintParts.Background) == DataGridViewPaintParts.Background)
{
    var backColor = elementState.HasFlag(DataGridViewElementStates.Selected)
        ? cellStyle.SelectionBackColor
        : cellStyle.BackColor;

    using var cellBackground = new SolidBrush(backColor);
    myBuffer.Graphics.FillRectangle(cellBackground, cellBounds);
}

2: In order to correctly define the border so that it matches a "normal" button cell (so that the button does not fill the whole cell), you can add the following code:

// Calculate the area in which to draw the button.
var buttonArea = cellBounds;
var cellPadding = cellStyle.Padding;
var buttonAdjustment = BorderWidths(advancedBorderStyle);
buttonArea.X += cellPadding.Left + buttonAdjustment.Left;
buttonArea.Y += cellPadding.Top + buttonAdjustment.Top;
buttonArea.Width -= cellPadding.Horizontal + buttonAdjustment.Left + buttonAdjustment.Right;
buttonArea.Height -= cellPadding.Vertical + buttonAdjustment.Top + buttonAdjustment.Bottom;
jrn6270
  • 61
  • 11