71

I want to use my DataGridView only to show things, and I want the user not to be able to select any row, field or anything from the DataGridView.

How can I do this?

Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
Mahdi Tahsildari
  • 13,065
  • 14
  • 55
  • 94
  • 3
    Not being able to select is really bad user interface design (very annoying to the user). What if the user wants to copy something from your report? I think read-only will suffice (as described in answers below). – banging Jul 04 '12 at 15:58

12 Answers12

147

I'd go with this:

private void myDataGridView_SelectionChanged(Object sender, EventArgs e)
{
    dgvSomeDataGridView.ClearSelection();  
}

I don't agree with the broad assertion that no DataGridView should be unselectable. Some UIs are built for tools or touchsreens, and allowing a selection misleads the user to think that selecting will actually get them somewhere.

Setting ReadOnly = true on the control has no impact on whether a cell or row can be selected. And there are visual and functional downsides to setting Enabled = false.

Another option is to set the control selected colors to be exactly what the non-selected colors are, but if you happen to be manipulating the back color of the cell, then this method yields some nasty results as well.

Pascal
  • 1,255
  • 5
  • 20
  • 44
edhubbell
  • 2,218
  • 1
  • 16
  • 17
  • Question "How do I change the datagridview selected row background color?" describes how to set background and foreground color for the selected row: Question
    This worked good enough for me.
    – user1036944 May 22 '13 at 23:03
  • Add the clearSelection to any dhtmlgrid or dataprocessor event before sending the data. Typo correction: myGrid.clearSelection(); – Jajikanth pydimarla Apr 10 '17 at 14:52
  • Another reason to do this - when the cell backcolor is critical for relaying information. By disallowing cell select on a readonly datagridview you can ensure that backcolor is always visible to the user! – DAG Aug 14 '19 at 12:42
  • @edhubbel this code is causing me an Infinite loop, because if I call ClearSelection(); then the SelectionChanged(); triggered automatically and this will create a loop. – Thrainder Jul 11 '21 at 16:10
21

You may set a transparent background color for the selected cells as following:

DataGridView.RowsDefaultCellStyle.SelectionBackColor = System.Drawing.Color.Transparent;
ale
  • 10,012
  • 5
  • 40
  • 49
user4101525
  • 211
  • 2
  • 2
  • 1
    It will cause some problems. The selected cell's background won't paint on invalidates. I had different grids on different page controls that had this problem and it took me hours to find the it was the `Transparent` color! – saastn Jun 25 '19 at 09:35
15

Enabled property to false

or

this.dataGridView1.DefaultCellStyle.SelectionBackColor = this.dataGridView1.DefaultCellStyle.BackColor;
this.dataGridView1.DefaultCellStyle.SelectionForeColor = this.dataGridView1.DefaultCellStyle.ForeColor;
Machavity
  • 30,841
  • 27
  • 92
  • 100
Ramgy Borja
  • 2,330
  • 2
  • 19
  • 40
3

I fixed this by setting the Enabled property to false.

Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
Rick
  • 39
  • 2
3

If you don't need to use the information in the selected cell then clearing selection works but if you need to still use the information in the selected cell you can do this to make it appear there is no selection and the back color will still be visible.

private void dataGridView_SelectionChanged(object sender, EventArgs e)
    {
        foreach (DataGridViewRow row in dataGridView.SelectedRows)
        {
            dataGridView.RowsDefaultCellStyle.SelectionBackColor = row.DefaultCellStyle.BackColor;
        }
    }
PWCoder
  • 93
  • 6
2

This worked for me like a charm:

row.DataGridView.Enabled = false;

row.DefaultCellStyle.BackColor = Color.LightGray;

row.DefaultCellStyle.ForeColor = Color.DarkGray;

(where row = DataGridView.NewRow(appropriate overloads);)

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Paddy
  • 21
  • 1
2

you have to create a custom DataGridView

`

namespace System.Windows.Forms
{
    class MyDataGridView : DataGridView
    {
        public bool PreventUserClick = false;

        public MyDataGridView()
        {

        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (PreventUserClick) return;

            base.OnMouseDown(e);
        }
    }
}

` note that you have to first compile the program once with the added class, before you can use the new control.

then go to The .Designer.cs and change the old DataGridView to the new one without having to mess up you previous code.

private System.Windows.Forms.DataGridView dgv; // found close to the bottom

private void InitializeComponent() {
    ...
    this.dgv = new System.Windows.Forms.DataGridView();
    ...
}

to (respective)

private System.Windows.Forms.MyDataGridView dgv;

this.dgv = new System.Windows.Forms.MyDataGridView();
  • This approach prevents the user from selecting anything but still lets the coder select rows programmatically. Also achieves the goal of preventing user selection without a bunch of sloppy visual artifacts. Enables coder to enable/disable user selection on the fly. – CodeWriter23 Sep 17 '22 at 17:52
1

I found setting all AllowUser... properties to false, ReadOnly to true, RowHeadersVisible to false, ScollBars to None, then faking the prevention of selection worked best for me. Not setting Enabled to false still allows the user to copy the data from the grid.

The following code also cleans up the look when you want a simple display grid (assuming rows are the same height):

int width = 0;
for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
    width += dataGridView1.Columns[i].Width;
}

dataGridView1.Width = width;
dataGridView1.Height = dataGridView1.Rows[0].Height*(dataGridView1.Rows.Count+1);
Community
  • 1
  • 1
SharpC
  • 6,974
  • 4
  • 45
  • 40
1

Here's what has always worked for me to disable the default selection in a class inherited from DataGridView:

// REQUIRES: SelectionMode = DataGridViewSelectionMode.FullRowSelect
protected override void SetSelectedRowCore(int rowIndex, bool selected)
{       
    base.SetSelectedRowCore(rowIndex, selected && ALLOW_DEFAULT_SELECTION);
}
bool ALLOW_DEFAULT_SELECTION = false;

Usually the goal is to disable it entirely (in order to implement our own custom selection and drawing process). When the goal is to allow the default selection only at specific times the boolean can be wrapped like so:

public void SelectRowExplicitly(int index, bool selected = true)
{
    try
    {
        ALLOW_DEFAULT_SELECTION = true;
        Rows[index].Selected = selected;
    }
    finally
    {
        ALLOW_DEFAULT_SELECTION = false;
    }
}
IVSoftware
  • 5,732
  • 2
  • 12
  • 23
0

I liked user4101525's answer best in theory but it doesn't actually work. Selection is not an overlay so you see whatever is under the control

Ramgy Borja's answer doesn't deal with the fact that default style is not actually a color at all so applying it doesn't help. This handles the default style and works if applying your own colors (which may be what edhubbell refers to as nasty results)

dgv.RowsDefaultCellStyle.SelectionBackColor = dgv.RowsDefaultCellStyle.BackColor.IsEmpty ? System.Drawing.Color.White : dgv.RowsDefaultCellStyle.BackColor;
dgv.RowsDefaultCellStyle.SelectionForeColor = dgv.RowsDefaultCellStyle.ForeColor.IsEmpty ? System.Drawing.Color.Black : dgv.RowsDefaultCellStyle.ForeColor;
Nick Slavsky
  • 1,300
  • 3
  • 19
  • 39
Bengineer
  • 21
  • 5
0

Its in VB, but shouldnt be difficult to translate to C#: If you want to lock datagridview, use dg.ReadOnly == True;

If you want to prevent user from selecting another row, just remember old selection and based on condition set or not set the row which shall be selected. Assuming, that multiselection is turned off:

    Private Sub dg_SelectionChanged(sender As Object, e As EventArgs) Handles dg.SelectionChanged
    Static OldSelection As Integer
      If dg.Rows.Count > 0 Then
          If dg.SelectedRows(0).Index <> OldSelection And YOURCONDITION Then
            dg.Rows(OldSelection).Selected = True
          End If

        OldSelection = dg.SelectedRows(0).Index
      End If
    End Sub
Werner
  • 95
  • 8
-3

Use the DataGridView.ReadOnly property

The code in the MSDN example illustrates the use of this property in a DataGridView control intended primarily for display. In this example, the visual appearance of the control is customized in several ways and the control is configured for limited interactivity.

Observe these settings in the sample code:

// Set property values appropriate for read-only
// display and limited interactivity
dataGridView1.AllowUserToAddRows = false;
dataGridView1.AllowUserToDeleteRows = false;
dataGridView1.AllowUserToOrderColumns = true;
dataGridView1.ReadOnly = true;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.MultiSelect = false;
dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
dataGridView1.AllowUserToResizeColumns = false;
dataGridView1.ColumnHeadersHeightSizeMode = 
DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
dataGridView1.AllowUserToResizeRows = false;
dataGridView1.RowHeadersWidthSizeMode = 
DataGridViewRowHeadersWidthSizeMode.DisableResizing;
Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
Angshuman Agarwal
  • 4,796
  • 7
  • 41
  • 89
  • 4
    If i could down vote I would. Not enough rep yet. However readonly does nothing for preventing a user to select a cell. – JSON Mar 24 '16 at 20:15