Arvo Bowen
Arvo Bowen

Reputation: 4929

Best way to stop a datagridview object from getting clicked and stealing focus

I have two datagridviews on my form. I have one (dgv1) that I edit the data in and one (dgv2) that is used for viewing only (catching click actions). For example, I might be editing a cell (text) in dgv1 and need to double click on a row in dgv2 to put the contents into dgv1 (similar to a quick copy/paste). Currently I have to use the right mouse double click event on dgv2 because if at any time I left click or left double click the focus will move from dgv1 to dgv2 and stop editing the dgv1 cell I'm working on.

I want to see if it's possible to be able to do exactly what I'm doing by double right clicking on dgv2 with the left mouse click button?

The only thing I could come up with is to try and find a way to disable the left mouse click event but I was hoping to basicly just make it "not respond" like it does when you double RIGHT click on the cell/row.

Ideas?

Edit: Example of dgv2 CellMouseDoubleClick event

private void dgv2_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.Button != MouseButtons.Right) return;

    DataGridView dgvSrc = (DataGridView)sender;
    DataGridView dgvDest = dgv1;

    DataGridViewCell cellSrc = dgvSrc.Rows[e.RowIndex].Cells["dgv2VariableName"];

    foreach (DataGridViewCell cell in dgvDest.SelectedCells)
    {
        if (cell.IsInEditMode && dgvDest.CurrentCell.EditType == typeof(DataGridViewTextBoxEditingControl))
        {
            //Target inserting the variable in the current selected edited area inside the textbox
            TextBox editBox = (TextBox)dgvDest.EditingControl;

            int selStartPos = editBox.SelectionStart;
            int selEndPos = selStartPos + editBox.SelectionLength;

            editBox.Text = editBox.Text.Substring(0, selStartPos) + cellSrc.Value.ToString() + editBox.Text.Substring(selEndPos);
            editBox.SelectionStart = selStartPos + cellSrc.Value.ToString().Length;
        }
        else
        {
            //Just override the entire cell
            cell.Value = cellSrc.Value;
        }
    }
}

Upvotes: 1

Views: 2376

Answers (1)

Reza Aghaei
Reza Aghaei

Reputation: 125197

You can make your DataGridView non-selectable and also make it read-only. Then when user double click on its cells, it doesn't steal focus from the focused control.

To make it read only, it's enough to set its ReadOnly property to true. To make in non-selectable, you can derive from DataGridView and in constructor, make in non-selectable:

SetStyle(ControlStyles.Selectable, false);

Note

Since SetStyle is prottected, you can not use it outside of your control. But you can call it using reflection. Since it's a useful method, you can create an extension method like what I used here to simulate an on-screen keyboard. Then you can use it against all controls. Here is the settings which I used for second DataGridView:

this.dataGridView2.SetStyle(ControlStyles.Selectable, false);
this.dataGridView2.ReadOnly = true;

And here is the extension method which I used to expose SetStyle:

public static class Extensions
{
    public static void SetStyle(this Control control, ControlStyles flags, bool value)
    {
        Type type = control.GetType();
        BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
        MethodInfo method = type.GetMethod("SetStyle", bindingFlags);
        if (method != null)
        {
            object[] param = { flags, value };
            method.Invoke(control, param);
        }
    }
}

Upvotes: 2

Related Questions