2
votes

The DataGridView control allows you to click the row headers and select the rows (the whole row is highlighted), or use the mouse and click and drag to select multiple rows, etc. to select all of them.

Anyway, I need the rows to stay selected if the user decides to click on a cell somewhere in the DataGridView. So, if the user clicks on a cell in one of the selected rows, the selected rows should stay highlighted. If the user clicks a cell in a different, unselected row, all the currently selected cells should stay highlighted. As a matter of fact, I don't want the row selection to change at all unless they use the row headers.

Is this something that's easy to configure, or am I in for a few days of hacking?

3
Ok, well, I thought of different way to achieve what I wanted. You guys don't have to bother answering this one anymore! Thanks to everyone.Isaac Bolinger
Best practice is to post your own solution and accept it - you may be helping someone in the future.Kirk Broadhurst
Meanwhile you'd be better off simply training your users that when they click a cell they are selecting a row. They should learn that quickly - it's default behaviour.Kirk Broadhurst
No it isn't. You have to have it on FullRowSelect for that to be true. The little triangle on the rowheader doesn't mean the row is in the collection of selected rows. By default I think its set to RowHeaderSelect. Anyway, the default behavior of the datagridview is utter BS, I've really changed it alotIsaac Bolinger
Anyway, I haven't solved this problem... I only changed my design so I didn't have to solve it :(Isaac Bolinger

3 Answers

2
votes

Not easy to configure. Spend a few days with the DataGridView control, and you'll notice that nothing about it is easy to configure, unless the developers happened to decide to expose it as a property. And only the simplest of things are exposed this way, so don't waste too much time looking.

Of course, it is possible. I've spent way too much of my life subclassing the DataGridView control and overriding built-in behavior that strikes me as stupid. But I really don't recommend it to anyone.

More to the point, you should also seriously reconsider whether you even want to make this particular change. I would have no idea what was going on if software started to do that. I'd immediately suspect that my shift key or mouse button were stuck and try banging them unstuck. The next step would be restarting my computer. Overall, not a very positive user experience. This isn't the way that the control behaves for a reason. Do consider very carefully what it actually means semantically for a cell to be highlighted—generally, the implication is that you can change the value of or delete all selected cells at once. If that's not how your implementation is going to work, you probably shouldn't do it in the first place.

2
votes

I would say its not a good idea to to this and its unwanted behavior from users perspective you will need to teach them that your rows get selected only by row headers not by clicking on them (believe me they will be frustrated). In a way you are refraining the user from selecting the rows at all.

That said, if you are keen to go on this design then you will need to do it yourself. GridView doesn't have any built behaviour for this. You can fiddle with RowChanged events and CanSelect properties & do some overriding.

And then there's a RowHeaderMouseClick event you can utilize for Row Selection from Row Header.

1
votes

I managed to circumvent this using, er... DataGridView subclassing, sorry.

This can be done cleanly, adding a couple of delegate before and after the internal mechanism that unselect them:

class SimpleDataGridView : DataGridView {

    public Action<DataGridViewCellMouseEventArgs> BeforeCellMouseDown;
    public Action<DataGridViewCellMouseEventArgs> AfterCellMouseDown;

    protected override void OnCellMouseDown(DataGridViewCellMouseEventArgs e) {
        if(BeforeCellMouseDown != null)
            BeforeCellMouseDown(e);

        base.OnCellMouseDown(e);

        if(AfterCellMouseDown != null)
            AfterCellMouseDown(e);
    }
}

Then, you can use it this way, in your constructor. Replace "yourCondition" by the way you want to determine wether the selection has to be kept or not.

IEnumerable<DataGridViewRow> sel = null;

dataGridView1.BeforeCellMouseDown = 
    e => {
        if (yourCondition)
            sel = dataGridView1.SelectedRows.OfType<DataGridViewRow>();
        else
            sel = null;
    };

dataGridView1.AfterCellMouseDown = 
    e => {
        if(sel != null) {
            foreach(var row in sel)
                row.Selected = true;
        }
    };