Link to home
Start Free TrialLog in
Avatar of e_livesay
e_livesayFlag for United States of America

asked on

Select multiple rows in a C# DataGridView programmatically?

I need to select multiple rows in a DataGridView (MultiSelect = true, SelectionMode = RowHeaderSelect). From the user interface there is no problem.  I simply hold down the <CTRL> key and click on all of the row headers one-by-one.  When I click on a row, all of the cells in the row are redrawn with a blue background indicating that they have been selected and the arrow that appears in the row header column is updated so that it is in the last row header that I clicked.

When attempting to replicate this behavior programmaticly I run into a problem.  The code shown below is supposed to do this - first it fills the DataGridView with data (the DataGridView is not DataBound) and second it selects all of the rows.  The System.Diagnostics lines output what I would expect when there are 3 rows in the DataGridView; before = 0 and after = 3. However, on the UserInterface the background of the cells in the first row are blue but the cells in the second and third rows are white and the triangle is still sitting in the row header of the first row.  I expected it to be in the row header of the third row.

I tried to select all cells of all rows using the line that has been commented-out in the second loop of the code below but that didn't solve my problem.

Any thoughts on how to fix this (without making the DataGridView DataBound)?

Thanks.

public void                     displayMeasurements(List<clsMeasurement> L_Msrmt)
{
     DGV.Rows.Clear();
     foreach (clsMeasurement Msrmt in L_Msrmt)
     {
          int row = DGV.Rows.Add();

          DGV.Rows[row].Cells["col_x"].Value = Msrmt.x;
          DGV.Rows[row].Cells["col_y"].Value = Msrmt.y;
          DGV.Rows[row].Cells["col_x"].Value = Msrmt.y;
          DGV.Rows[row].Tag                           = Msrmt;
     }

     System.Diagnostics.Trace.WriteLine("before = " + DGV.SelectedRows.Count.ToString());
     DGV.ClearSelection();
     foreach (DataGridViewRow r in DGV.Rows)
     {
          r.Selected = true;
          //foreach (DataGridViewCell c in r.Cells) c.Selected = true;
     }
     System.Diagnostics.Trace.WriteLine("after = " + DGV.SelectedRows.Count.ToString());
}
ASKER CERTIFIED SOLUTION
Avatar of Luis Pérez
Luis Pérez
Flag of Spain image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of e_livesay

ASKER

Roland,

   Odd stuff.  I have tried this on a Windows XP machine and a Windows 7 machine and on both of them I am getting the same results - only the cells of the first row have blue backgrounds.

   Below are the settings from the [UserControl].Designer.cs file.

   Thanks for the feedback.

//
// DGV
//
this.DGV.AllowUserToAddRows = false;
this.DGV.AllowUserToDeleteRows = false;
this.DGV.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.DGV.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.DGV.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.col_modfile,
this.col_Angle,
this.col_RMS_fitError});
this.DGV.ContextMenuStrip = this.contextMenuStrip1;
this.DGV.Location = new System.Drawing.Point(3, 3);
this.DGV.Name = "DGV";
this.DGV.Size = new System.Drawing.Size(732, 376);
this.DGV.TabIndex = 0;
this.DGV.CellValidated += new System.Windows.Forms.DataGridViewCellEventHandler(this.DGV_CellValidated);
this.DGV.CellValidating += new System.Windows.Forms.DataGridViewCellValidatingEventHandler(this.DGV_CellValidating);
Same results even applying all your properties to my grid. All rows are selected well. Sorry, I don't know what to do more.
The MultiSelect property of the grid should be True in order to be able to select in more than one row.

And instead of looping through the cells, simply call the SelectAll method of the grid.
Thanks for the feedback.

The MultiSelect property is set to true when I look at the Property page for the DataGridView (i.e., in the MSVS 2010 Designer).  I suppose that the value of the MultiSelect proeprty does not appear in the Designer.cs file because 'true' is the default value for the MultiSelect property.  Similarly, the Enabled property is true in the Property page but it does not appear in Designer.cs.

Actually, I'm not looping through the cells.  I tried doing so at one point but that didn't help matters.

James - does the example code above work for you like it does for Roland?
You are right, default values do not need to be set and thus are not defined in Designer.cs.

Have you tried SelectAll?

Have you search your code in case the MultiSelect property is changed in the code somewhere?

Sorry, I do not have any unbound DataGridView in my environment right now and do not have time to set up a test.
Thanks for all the help.  The issue has turned out to not be with the code that I originally submitted at all but with the way that I was using it.  Since Roland Deschain confirmed that the code was working in his initial replies I'm going to award the points to him.

Below are the details of what was going on.

The displayMeasurements(List<clsMeasurement> L_Msrmt) routine shown in my first post resides in a UserControl, UC_Bar.  An instance of UC_Bar sits on a Form that was opened using the following code:

frmFoo f = new frmFoo();
f.Initialize(L_Measurements);   // L_Measurements is of type List<clsMeasurement>
f.ShowDialog();

The Initialize(...) routine of frmFoo calls UC_Bar's displayMeasurements(...) routine (i.e., the one shown in my first post) which I thought would lead to all rows being selected.  Apparently calling ShowDialog() undid the selection of all except the first row.

To fix the issue I did a few things.  First, I got rid of the Initialize(...) routine altogether and added a public List<clsMeasurements> named myMeasurements to frmFoo.  This allowed the above code to be replaced with the following:

frmFoo f = new frmFoo();
f.myMeasurements = L_Measurements;
f.ShowDialog();

I also added a 'Load' EventHandler to frmFoo which initializes the instance of UC_Bar that sits on frmFoo:

private void frmFoo_Load(object sender, EventArgs e)
{
   uC_Bar.displayMeasurements(myMeasurements);
}
I very much appreciated Roland's effort to test the code snippet that I submitted - it was very useful confirmation that forced me to find the source of the problem which happened to not be in the code that I submitted at all.  Thanks for the help.