Link to home
Start Free TrialLog in
Avatar of ElrondCT
ElrondCTFlag for United States of America

asked on

Enter DataGrid at correct cell

In VB .NET 2003, I have a DataGrid with five columns. I have noticed that if I tab into the grid from the other controls on the form, the cell highlighted is the one that was last the CurrentCell when I was previously in the DataGrid. That's true even if I've moved to a different set of records, which isn't desirable behavior. (If there are no longer as many rows, focus goes to the first row, same column.) I thought of simply setting the .CurrentCell to the first row, first column in the Enter event handler for the DataGrid, but if a user clicks on a cell to make a change to it, I want that click to be recognized and focus to go immediately to that cell.

A couple of possibilities came to my mind to do this:

1) Change the CurrentCell in the Leave event handler. But I'm finding that if I do this, if I leave by means of clicking on a CheckBox, the CheckBox is changed but then focus returns to the DataGrid. (A second click on the CheckBox will get focus to stay there, but this kind of behavior will drive users nuts.)

2) Distinguish between entering the DataGrid via a tab entry (for which I'd set dg.CurrentCell = New DataGridCell(0, 0)) and via a mouse click. But I don't know how to do this.

If there's another way to do it, I'm open to that as well.
Avatar of Sancler
Sancler

It's a bit late for me (I'm in the UK) but I see this has been hanging around now for 24 hours so here's a suggestion.  Not actually an answer ;-(

Re

>>
2) Distinguish between entering the DataGrid via a tab entry (for which I'd set dg.CurrentCell = New DataGridCell(0, 0)) and via a mouse click. But I don't know how to do this.
<<

Nor do I.  Hence no response before now.  But the way I would go about trying to find out how to do it is by sticking debug code in the Enter and MouseEnter events and working back from what that revealed.  I've just had a play with this

    Private Sub DataGrid1_Enter(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGrid1.Enter
        Static i As Integer = 0
        Debug.WriteLine("Enter" & i.ToString & " Col:" & DataGrid1.CurrentCell.ColumnNumber.ToString & " row:" & DataGrid1.CurrentCell.RowNumber.ToString)
        i += 1
    End Sub

    Private Sub DataGrid1_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGrid1.MouseEnter
        Static i As Integer = 0
        Debug.WriteLine("MouseEnter" & i.ToString & " Col:" & DataGrid1.CurrentCell.ColumnNumber.ToString & " row:" & DataGrid1.CurrentCell.RowNumber.ToString)
        i += 1
    End Sub

and (although it's too late for me to work it out at the moment) I reckon there should be enough revealed by that as to the order in which the events fire to be able to distinguish between tabbing into the grid and clicking into it with the mouse.

Let me know if it seems that way to you, too, sufficiently for you to crack it.  If not, I'll see what I can work up on it.

Roger
ASKER CERTIFIED SOLUTION
Avatar of Sancler
Sancler

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 ElrondCT

ASKER

Roger, when this whole project is done, I think I'm going to need to pay you royalties!

I played around Saturday with the mouse events (which I hadn't thought about until you mentioned them in your first message). MouseEnter doesn't really do what I want, since that fires if one simply puts the mouse over the control, whether or not you click. Unfortunately, it turns out that MouseDown fires _after_ the Enter event. That makes it a lot less useful, IMHO, but that's the way it goes. I didn't have a lot of time to work with them, though, which is why I didn't post back.

However, I think your idea in your second posting will work well. Putting flags on the other 40 controls on the form would be tedious, but it occurs to me that really what I want is that, if the user is displaying a different record from the one edited when last in the grid, tabbing will go to the first cell. If they've edited the grid and stayed within the record for the other controls, then I think it's fine, if they tab back to the grid, to have it go back to the last cell they edited. It won't look odd in that situation (and frankly people are unlikely to use tab to go back to the grid after moving on to other controls, as opposed to when entering a new record). So all I need to do is set a flag when a new record is displayed on the form, and check that flag on entry to the grid. If it's the first time entering the grid, turn off the glad and set DataGrid1.CurrentCell = New DataGridCell(0, 0); otherwise, don't do anything.

Thanks once again. The time you spend on these questions amazes me.
As I was putting the new code in, I thought, "Wait a second. I'm back where I started, since I still don't know whether I'm coming in with a tab or a mouse click." If the user uses the mouse to get to the grid on a new record, I want the mouse-selected cell to get focus, not the first. But it turns out that that's exactly why MouseDown fires after Enter. If I set the .CurrentCell in Enter, it'll get updated during MouseDown to the cell clicked on. That's exactly what I want, so I'm in good shape.
Another follow-up: What I described worked fine for ordinary cells. But my grid has two custom cell types: a ComboBox and a DateTimePicker. The ComboBox works fine with this, but the DTP grabs focus and won't let go if the Enter event handler changes the CurrentCell. However, it eventually occurred to me that I could set the CurrentCell whenever the record displayed changes. So I took the setting out of the Enter event handler, and now I have

    dg.CurrentCell = New DataGridCell(0, 0)

in the PositionChanged event handler for the CurrencyManager, followed by a .Focus for the first control on the form (because setting .CurrentCell seems to set the Focus to the grid), and everything is working as I want.