We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

How To: Keep track of selections in a Datagrid and Multi-Select rows

Like many others, I was looking for a viable solution that would allow a datagrid to select the whole row and then be able to handle mulitple selections using the Shift, and Control keys. FAQ 5.37 was a good start but only works if your datagrid displays the row header...which I would rather not have to. This solution is also perfect for determining which rows are selected and I even coded it into a simple to use property. Here's what you do.... Add a DataGrid with a TableStyle and a custom column style for each column. Of course to make it look right, you'll need to override the Edit method but have an empty implementation (just leaving the override Edit method empty is all that is necessary). Then overide the OnMouseDown method of the Datagrid to select the whole row and add the selected row to an ArrayList. Handling the multiple selections is just a matter of logic with using the Shift and Control (or both) keys. It mimics exactly how the Windows defaut ListView handles multiple selection. I have attached a fully working code sample and I'll also paste it below. Comments and questions welecome. --FamilyMan //--------------------------------------------- // This code is a modified version found originally at http://www.syncfusion.com/FAQ/WinForms/ // in a sample-file named: datagridbrowser-multiselect.zip namespace DataGridMultiSelect { using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Data.OleDb; /// /// Summary description for Form1. /// public class Form1 : System.Windows.Forms.Form { private MyDataGrid dataGrid1; /// /// Required designer variable. /// private System.ComponentModel.Container components = null; public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); } /// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.dataGrid1 = new MyDataGrid(); ((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).BeginInit(); this.SuspendLayout(); // // dataGrid1 // this.dataGrid1.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right); this.dataGrid1.DataMember = ""; this.dataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText; this.dataGrid1.Location = new System.Drawing.Point(24, 24); this.dataGrid1.Name = "dataGrid1"; this.dataGrid1.Size = new System.Drawing.Size(448, 280); this.dataGrid1.TabIndex = 0; // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(504, 341); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.dataGrid1}); this.Name = "Form1"; this.Text = "Form1"; this.Load += new System.EventHandler(this.Form1_Load); ((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).EndInit(); this.ResumeLayout(false); } #endregion /// /// The main entry point for the application. /// [STAThread] public static void Main() { Application.Run(new Form1()); } private void Form1_Load(object sender, System.EventArgs e) { // Set the connection and sql strings // assumes your mdb file is in your root string connString = @"Provider=Microsoft.JET.OLEDB.4.0;data source=C:orthwind.mdb"; string sqlString = "SELECT * FROM customers"; OleDbDataAdapter dataAdapter = null; DataSet _dataSet = null; try { // Connection object OleDbConnection connection = new OleDbConnection(connString); // Create data adapter object dataAdapter = new OleDbDataAdapter(sqlString, connection); // Create a dataset object and fill with data using data adapter's Fill method _dataSet = new DataSet(); dataAdapter.Fill(_dataSet, "customers"); connection.Close(); } catch(Exception ex) { MessageBox.Show("Problem with DB access- connection: " + connString + "\r\r query: " + sqlString + "\r\r\r" + ex.ToString()); this.Close(); return; } // Create a table style that will hold the new column style // that we set and also tie it to our customer's table from our DB DataGridTableStyle tableStyle = new DataGridTableStyle(); tableStyle.MappingName = "customers"; // since the dataset has things like field name and number of columns, // we will use those to create new columnstyles for the columns in our DB table int numCols = _dataSet.Tables["customers"].Columns.Count; MyGridColumn aColumnTextColumn ; for(int i = 0; i < numCols; ++i) { aColumnTextColumn = new MyGridColumn(); aColumnTextColumn.HeaderText = _dataSet.Tables["customers"].Columns[i].ColumnName; aColumnTextColumn.MappingName = _dataSet.Tables["customers"].Columns[i].ColumnName; tableStyle.GridColumnStyles.Add(aColumnTextColumn); tableStyle.RowHeadersVisible = false; } // make the dataGrid use our new tablestyle and bind it to our table dataGrid1.TableStyles.Clear(); dataGrid1.TableStyles.Add(tableStyle); dataGrid1.DataSource = _dataSet.Tables["customers"]; //force a move to set select on first row... this.dataGrid1.CurrentCell = new DataGridCell(0, 1); } } public class MyGridColumn : DataGridTextBoxColumn { protected override void Edit(System.Windows.Forms.CurrencyManager source, int rowNum, System.Drawing.Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible) { //don't call baseclass... } } public class MyDataGrid : DataGrid { private ArrayList mySelection = new ArrayList(); // Holds selected rows. private int myLastSelection; // Holds last row selected. #region OnMouseDown Method /// /// Override of OnMouseDown Method. Determines if clicks are in cell blocks and /// handles multiple selections. /// /// A MouseEventArgs that contains the event data. protected override void OnMouseDown(MouseEventArgs e) { // Determines location of mouse click. DataGrid.HitTestInfo hit = HitTest(e.X, e.Y); if (hit.Type == HitTestType.Cell) { if (e.Button == MouseButtons.Left) { // Determines selection type with ModifierKeys. switch (ModifierKeys) { case Keys.Shift: // Shift key has been held. // Reset all selected rows and mySelection. ResetSelection(); mySelection.Clear(); if(myLastSelection < hit.Row) // Top to bottom selections. { for (int i = myLastSelection; i <= hit.Row; ++i) { Select(i); mySelection.Add(i); } } else // Bottom to top selections. { for (int i = hit.Row; i <= myLastSelection; ++i) { Select(i); mySelection.Add(i); } } break; case Keys.Control: // Control key has been held. if(IsSelected(hit.Row)) // Row has already been selected. { // UnSelect the row, remove it from mySelection, // update myLastSelection (updating myLastSelection in this case // does not seem intuitive to me, but keeps with Microsoft tradition). UnSelect(hit.Row); mySelection.Remove(hit.Row); myLastSelection = hit.Row; } else { // Select the row, add it to mySelection, update myLastSelection. Select(hit.Row); mySelection.Add(hit.Row); myLastSelection = hit.Row; } break; case Keys.Shift | Keys.Control: // Shift AND Control keys have been held. if(myLastSelection < hit.Row) // Top to bottom selections. { for (int i = myLastSelection; i <= hit.Row; ++i) { Select(i); mySelection.Add(i); } } else // Bottom to top selections. { for (int i = hit.Row; i <= myLastSelection; ++i) { Select(i); mySelection.Add(i); } } break; default: // No keys held. A standard single click. // Reset all selected rows and mySelection. ResetSelection(); mySelection.Clear(); // Select the row, add it to mySelection, update myLastSelection. Select(hit.Row); mySelection.Add(hit.Row); myLastSelection = hit.Row; break; } } else { // TODO A good place to handle right-clicks... } } else { // Call the base OnMouseDown method to handle all other events. base.OnMouseDown(e); } } #endregion #region SelectedItems Property /// /// Gets or sets the SelectedItems Property. /// [Browsable(false)] public ArrayList SelectedItems { get { return mySelection; } set { // Reset all selected rows and mySelection. ResetSelection(); mySelection.Clear(); // Add to mySelection and Select the row(s). mySelection = value; foreach(int oneRow in mySelection) { Select(oneRow); } } } #endregion } }

Loader.
Live Chat Icon For mobile
Up arrow icon