Custom datagridview cell control

392 Views Asked by At

I've place my custom control into the DataGridView cell like it's discribes in this article.

But now I've find that after load form cell is displayed as simply TextBoxCell and control appears only after seting cursor to cell. As I undestand now that's happens because DataGridView reinitialize cell when setting cursor.

Is there ony way to make control visible always?

1

There are 1 best solutions below

0
On

Usually you should host controls in winfors forms datagridview cells as shown here

But if you need your control to be always visible, what you can do is make a custom column inheriting from DataGridViewImageColumn. Add the control to the datagridview. Set the DefaultCellStyle.Nullvalue of the control to a bitmap of the control you want always shown on the data gridview. Then using the cellMouseEnter event you can display and reposition the control to display over the image cell. This gives the appearance that your custom control is always visible without using as much resources as creating a new instance of your control for every row added to the datagridview. This will help performance quite a bit.

Here is what I did with my custom “AddRemove” usercontrol.

public class AddRemoveColumn : DataGridViewImageColumn
{
    private AddRemove SelectionControl = null;
    private Bitmap SelectionControlImage = null;

    public AddRemoveColumn()
    {
        SelectionControl = new AddRemove();
    }

    #region Set Up Column
    protected override void OnDataGridViewChanged()
    {
        base.OnDataGridViewChanged();
        if (DataGridView != null)
        {
            Activate();
        }
    }

    private void Activate()
    {
        SelectionControl.LostFocus += SelectionControl_LostFocus;
        this.DataGridView.CellMouseEnter += DataGridView_CellMouseEnter;
        this.DataGridView.BackgroundColorChanged += DataGridView_BackgroundColorChanged;

        this.DataGridView.RowHeightChanged += DataGridView_RowHeightChanged;
        SelectionControl.OnAddClicked += AddClicked;
        SelectionControl.OnRemoveClicked += RemoveClicked;


        this.DataGridView.Controls.Add(SelectionControl);
        SelectionControl.Visible = false;

        this.Width = SelectionControl.Width;
        SelectionControl.BackColor = this.DataGridView.BackgroundColor;
        
        this.DataGridView.RowTemplate.Height = SelectionControl.Height +1;

        foreach (DataGridViewRow row in DataGridView.Rows)
        {
            row.Height = SelectionControl.Height+1;
        }

        SetNullImage();
    }
    #endregion

    private void AddClicked(int RowIndex)
    {
        MessageBox.Show("Add clicked on index=" + RowIndex.ToString());
    }

    private void RemoveClicked(int RowIndex)
    {
        MessageBox.Show("Removed clicked on index=" + RowIndex.ToString());
    }

    private void SetNullImage()
    {
        if (SelectionControlImage != null)
        {

            SelectionControlImage.Dispose();
        }
        
        SelectionControlImage = new Bitmap(SelectionControl.Width, SelectionControl.Height);

        SelectionControl.DrawToBitmap(SelectionControlImage, new Rectangle(0, 0, SelectionControlImage.Width, SelectionControlImage.Height));

        this.DefaultCellStyle.NullValue = SelectionControlImage;
    }

    private void DataGridView_RowHeightChanged(object sender, DataGridViewRowEventArgs e)
    {
        if (e.Row.Height <= 40)
        {
            e.Row.Height = 40;
        }

        SelectionControl.Visible = false;
        SetPosition(Index, e.Row.Index);
    }

    private void DataGridView_BackgroundColorChanged(object sender, EventArgs e)
    {
        SelectionControl.BackColor = this.DataGridView.BackgroundColor;


        SetNullImage();

    }

    private void SelectionControl_LostFocus(object sender, EventArgs e)
    {
        SelectionControl.Visible = false;
    }

    private void SetPosition(int ColumnIndex, int RowIndex)
    {
        Rectangle celrec = this.DataGridView.GetCellDisplayRectangle(ColumnIndex, RowIndex, true);//.Rows[e.RowIndex].Cells[e.ColumnIndex].GetContentBounds();

        int x_Offet = (celrec.Width - SelectionControl.Width)/ 2;
        int y_Offet = (celrec.Height - SelectionControl.Height)/2;

        SelectionControl.Location = new Point(celrec.X + x_Offet, celrec.Y + y_Offet);
        SelectionControl.Visible = true;
        SelectionControl.RowIndex = RowIndex;
    }

    private void DataGridView_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
    {
        if (e.ColumnIndex == this.Index)
        {
            SetPosition(e.ColumnIndex, e.RowIndex);
        }
    }
}

looks something like this;

enter image description here