简体   繁体   中英

Dynamic button column in DataGridView

This seems simple but it's becoming a source of great frustration for me. I'm creating a DataGridView and setting its DataSource to a list of an object which contains two properties... an int and a button. The first column works fine but the second is blank. After an SO search I realized my problem may be that my button column needed to be set as a DataGridViewButtonColumn, only when I try and set it as such it creates a new, third, button column.

How do I associate my auto-generated column as a DataGridViewButtonColumn? Here is a simplified version of my code.

List<EditGrid> items = new List<EditGrid>();

foreach (int number in numbers)
{
    EditGrid eg = new EditGrid();

    eg.number = number;
    eg.edit = new Button() { Text = "Edit", Name = "Edit" };

    items.Add(eg);
}

DataGridView d = new DataGridView
{
    Dock = DockStyle.Fill,
    AutoGenerateColumns = true,
    DataSource = items
};

Controls.Add(d);

I think you have to use some custom CellPainting and don't set the Text of DataGridViewButtonColumn to anything (this is by default an empty string). Like this:

private void dataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
        if (e.ColumnIndex > -1&&e.RowIndex > -1&&dataGridView.Columns[e.ColumnIndex] is DataGridViewButtonColumn)
        {                
            if (e.Value == null) return;
            e.Handled = true;
            e.PaintBackground(e.CellBounds, true);
            e.PaintContent(e.CellBounds);
            //prepare format for drawing string yourself.
            StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center };
            e.Graphics.DrawString(((Button)e.Value).Text, dataGridView.Font, Brushes.Black, e.CellBounds, sf);                
        }
}

In your case replace dataGridView with d , looks like that you create your DataGridView using code, if so, you have to register the CellPainting event handler yourself like this:

d.CellPainting += dataGridView_CellPainting;

UPDATE

to make your DataGridView have a DataGridViewButtonColumn first (without adding at design time), you have to add this code before setting your DataGridView's DataSource:

DataGridViewButtonColumn col = new DataGridViewButtonColumn();
col.HeaderText = "Your header";
col.Name = "button";
col.DataPropertyName = "Your DataSource Data member";//This is very important to match the corresponding Property or DataMember name of your DataSource.
col.FlatStyle = FlatStyle.Popup;//I suggest this because it looks more elegant.
d.Columns.Add(col);         
//----
d.DataSource = ...   

I found that setting the DisplayIndex for your Button column doesn't work, instead, you may want to set its DisplayIndex after the d.DataSource=... , and it works:

d.DataSource = ...   ;
d.Columns["button"].DisplayIndex = ...;
    var buttonCol = new DataGridViewButtonColumn();
    buttonCol.Name = "ButtonColumnName";
    buttonCol.HeaderText = "Header";
    buttonCol.Text = "Button Text";

    dataGridView.Columns.Add(buttonCol);
    foreach (DataGridViewRow row in dataGridView.Rows)
{
    DataGridViewButtonCell button = (row.Cells["ButtonColumnName"] as DataGridViewButtonCell);        
}

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