5

Goal

Currently looking to find a way how to select items from DataGridView and order it by the selected first at top.

Example

First selection by user:

Selected  Column1 Column2
             a       1
             b       2
             c       3
   x         d       4

Second selection...

Selected  Column1 Column2
             a       1
   x         b       2
             c       3
   x         d       4

Third selection...

Selected  Column1 Column2
   x          a      1
   x          b      2
              c      3
   x          d      4

Order

4th row 
2nd row
1st row

Summary

The 1st item selected by user was the 4th row, then the 2nd and lastly the 1st row.

Question

How can I get a list of the all rows in order as explained above?

Current Code

I created a checkbox column like so, so the user can see what they have selected.

DataGridViewCheckBoxColumn checkBoxColumn = new DataGridViewCheckBoxColumn();
checkBoxColumn.Name = "Selected";
checkBoxColumn.HeaderText = "Selected";
checkBoxColumn.ReadOnly = false;
productsView.Columns.Add(checkBoxColumn);

User then checks the checkbox to mark the selected records they desire, then they click a button to which opens another form.

But the order is mixed.

private void addBtn_Click(object sender, EventArgs e)
{

    foreach (var row in checkedRows)
    {
        DateTime dateTime = dateText.Value;
        string orderNumber = orderNumberText.Text;
    
        SelectedProducts form = new SelectedProducts(dateTime, orderNumber);
        form.ShowDialog();
    }

}
Eduards
  • 1,734
  • 2
  • 12
  • 37

2 Answers2

3

I think i would:

  1. Create a new list that would store my data depending on the new order.

    List<Item> SelectedItemList= new List<Item>
    
  2. Listen to the checkbox column value change. Add to the "SelectedList" when checkbox is checked or remove it when unchecked.( How to detect DataGridView CheckBox event change?)

    private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }
    
    private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
        if (dataGridView1.Rows.Count > 0)
        {
            if ((bool)dataGridView1.SelectedRows[0].Cells[2].Value) //the index of checkbox column
               SelectedItemList.Add(itemBindingSource.current as Item)//add data to the list
            else
               SelectedItemList.Remove(itemBindingSource.current as Item) // remove data to list
        }
    
    }
    
  3. Then use the list as parameter to the form display.

    SelectedProducts form = new SelectedProducts(SelectedItemList);
    form.ShowDialog();
    
Arjohn21
  • 66
  • 5
  • Just reading through all this, all makes sense until got to the point of `itemBindingSource.current as Item` Is this a valid code? – Eduards Feb 11 '21 at 12:19
  • You don't need such a workaround, just order the selected rows based on their index. – Reza Aghaei Feb 11 '21 at 13:59
  • @LV98 `itemBindingSource.current as Item` is just a way of getting the current selected row and adding/removing it from the `SelectedItemList`. The concept is that you get the current selected row and add/remove it to the `SelectedItemList` (or array if you prefer). – Arjohn21 Feb 13 '21 at 08:40
2

You don't need to track the selection by each check-change. Just get the checked rows when you need them:

var checkedRows = dataGridView1.SelectedRows.Cast<DataGridViewRow>()
    .Where(r => (bool)r.Cells["Selected"].Value == true)
    .ToList();
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • In general you should not have any dependency to the order of the selection, anyways, above code will do the trick for you, – Reza Aghaei Feb 11 '21 at 13:58
  • That simple aha! :D Just did so much alterations. – Eduards Feb 11 '21 at 14:08
  • The suggestion in the other answer will work, but you really don't need such a workaround :) – Reza Aghaei Feb 11 '21 at 14:13
  • 1
    I changed it a bit as I figured out you are not relying on SelctedRows, instead you have your own checkbox column. You even don't need order-by. Just stop tracking selection, instead, get the checked rows when you need. – Reza Aghaei Feb 11 '21 at 14:25
  • Thanks for noticing. Good job there's people like to who can make life easier with lesser coding :D – Eduards Feb 11 '21 at 14:41
  • No problem at all :) – Reza Aghaei Feb 11 '21 at 14:42
  • How would I then get the values for any column? – Eduards Feb 11 '21 at 15:36
  • 1
    The result of the query is a `List` and for each row, you can use its `Cells` property. You also have the option of projecting the result, before calling `ToList`, for example: `.Select(r=>(THE COLUMN TYPE)r.Cells["THE COLUMN NAME"].Value)`. – Reza Aghaei Feb 11 '21 at 15:44
  • What's the data source of your DataGridView? – Reza Aghaei Feb 11 '21 at 15:45
  • It's a `DS.Tables[0]`. Using SQL Query into a `DataSet`. Nothing fancy, no dapper. – Eduards Feb 11 '21 at 15:47
  • What's the data source of your DataGridView? You may find [`DataBoundItem`](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.datagridviewrow.databounditem?view=net-5.0&WT.mc_id=DT-MVP-5003235) property of the row useful. If the data source is `DataTable`, `DataBound` contains instance of the `DataRowView` behind the row. You may project to `r=>(DataRowView)r.DataBoundItem` in result, or project it to something more useful like `r=> new {X = ((DataRowView)r.DataBoundItem).Field("X"), Y = ((DataRowView)r.DataBoundItem).Field("Y")}` – Reza Aghaei Feb 11 '21 at 15:50
  • If it looks confusing, just ignore for now :) – Reza Aghaei Feb 11 '21 at 15:51
  • Yes a little aha! I'll take a deeper look into it. I am currently looking into how to filter via `textchanged`, but the checkboxes lose values.. – Eduards Feb 11 '21 at 15:55
  • That's obvious. The checkbox column that you created is an unbound column and doesn't have a backing field in `DataTable`, it's just a column in DataGridView. If you need to keep the checked status, you need to have it in your data table and create a bound column. – Reza Aghaei Feb 11 '21 at 15:59
  • I've sorted that, using dapper. Thanks for the tip ! – Eduards Feb 12 '21 at 11:15
  • Hi, I have unchecked the checkboxes.. and it still shows the previous items selected. – Eduards Feb 12 '21 at 12:43
  • Well, it's hard to guess what may be the problem. Make sure you are using bound columns. – Reza Aghaei Feb 14 '21 at 17:41
  • All fully working now. Just out of curiosity where did you learn to code? – Eduards Feb 14 '21 at 20:30
  • At work and at home during during work projects and personal R&Ds - I've never read a whole book, but read many articles and book chapters with regards to the projects/topics that I was working on. – Reza Aghaei Feb 15 '21 at 07:30
  • Have you got any recommendations ? – Eduards Feb 15 '21 at 08:10