Behrooz
Behrooz

Reputation: 1734

How do I make my own DataGridView Column

What I'm trying to do is making

I read this toturial and made my own DataGridViewBarColumn, but I don't have the slightest clue how I should implement something like this.

Performance doesn't matter even though there can be upwards of 100K rows in a DataGridView, I'll take care of optimizations later.

I think they're done the same way, so I'm asking them in one question

Upvotes: 1

Views: 420

Answers (1)

jtabuloc
jtabuloc

Reputation: 2535

What I can give you is a starting point to achieve it:

First, Prepare your binding and create your DataGridViewComboBoxColumn.

private List<string> list = new List<string>();

public Form1()
{
        InitializeComponent();

        // Data source for you dropdown list
        list.Add("First Option");
        list.Add("Second Option");
        list.Add("Third Option");

        dataGridView1.AutoGenerateColumns = false;
        dataGridView1.MultiSelect = false;
        dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
        dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
        dataGridView1.CellValidating += new DataGridViewCellValidatingEventHandler(dataGridView1_CellValidating);
        dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);
        dataGridView1.DataError += dataGridView1_DataError;

        // Formatting your ComboBox
        DataGridViewComboBoxColumn comboColumn = new DataGridViewComboBoxColumn();
        comboColumn.FlatStyle = FlatStyle.Flat;
        comboColumn.HeaderText = "Hybrid Data Grid Column";
        comboColumn.DataPropertyName = "Tag";
        //comboColumn.DataSource = list;        

        dataGridView1.Columns.Add(comboColumn);
        dataGridView1.DataSource = list;

}

Second, Attached an event for editing once you type:

    private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
    {
        var combo = ((DataGridView)sender).CurrentCell as DataGridViewComboBoxCell;
        if (combo == null)
        {
            return;
        }
        if (!combo.Items.Contains(e.FormattedValue))
        {
            // Add the text you type into you bound list and refresh binding
            list.Add(e.FormattedValue.ToString());
            DataGridViewComboBoxColumn col = ((DataGridView)sender).CurrentCell.OwningColumn as DataGridViewComboBoxColumn;
            col.Items.Clear();
            col.Items.AddRange(list);
        }

        // Display what you type
        ((DataGridView)sender).CurrentCell.Value = e.FormattedValue;
    }

    private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        ComboBox comboControl = e.Control as ComboBox;
        if (comboControl != null)
        {
            if (comboControl.DropDownStyle != ComboBoxStyle.DropDown)
            {
                comboControl.DropDownStyle = ComboBoxStyle.DropDown;
            }
            //Update Items if list has changed (assumes items can't be deleted)
            if (comboControl.Items.Count != list.Count)
            {
                DataGridViewComboBoxColumn col = ((DataGridView)sender).CurrentCell.OwningColumn as DataGridViewComboBoxColumn;
                col.Items.Clear();
                col.Items.AddRange(list.ToArray());
                //Note: current cell's items don't appear to be refreshed by the lines above
                comboControl.Items.Clear();
                comboControl.Items.AddRange(list.ToArray());
            }
        }
    }

Sample Output:

enter image description here

Note : Since we are adding text input in our bound list it might happen that once you click to dropdown option you will see the additional input. So, I will leave it to you to polish it up.

Upvotes: 2

Related Questions