DataGridView에서 셀을 고칠 때 F2를 누르면 편집 모드로 들어가는데, 이때 커서 위치가 생각과 다를 때가 있습니다. 엑셀에 익숙한 사용자는 F2를 누르면 커서가 글자 맨 끝에 있기를 기대하고, 반대로 값을 통째로 바꾸는 입력 화면이라면 내용 전체가 선택된 상태가 편합니다. 두 동작 모두 KeyDown에서 F2를 가로채 직접 BeginEdit를 호출하면 원하는 대로 맞출 수 있습니다.

커서를 텍스트 맨 끝으로

    Private Sub DataGridView_KeyDownd(sender As Object, e As KeyEventArgs)
        If e.KeyCode = Keys.F2 Then
            e.Handled = True
            sender.BeginEdit(False)
            Dim tbCell As System.Windows.Forms.DataGridViewTextBoxEditingControl = sender.EditingControl
            tbCell.Select(tbCell.Text.Length, 0)
        End If
    End Sub

e.Handled = True로 기본 F2 처리를 막고, BeginEdit(False)로 아무것도 선택하지 않은 채 편집 모드에 들어갑니다. 그다음 편집 중인 셀 안에 실제로 떠 있는 텍스트박스, 즉 EditingControl을 꺼내서 Select(시작위치, 길이)로 커서를 글자 수 위치에 길이 0으로 놓습니다. 결과적으로 커서가 맨 끝에서 깜박이게 됩니다.

광고

내용 전체 선택

    Private Sub DataGridView_KeyDownd(sender As Object, e As KeyEventArgs)
        If e.KeyCode = Keys.F2 Then
            e.Handled = True
            sender.BeginEdit(True)
        End If
    End Sub

이쪽은 더 간단합니다. BeginEdit의 인자를 True로 주면 셀 내용 전체가 선택된 상태로 편집이 시작되니, 사용자가 바로 타이핑하면 기존 값이 새 값으로 바뀝니다.

BeginEdit가 돌려주는 값과 예외

BeginEdit(selectAll As Boolean)은 현재 셀을 편집 모드로 바꾸는 메서드입니다. 인자는 위에서 본 대로 셀 내용을 모두 선택할지(True) 아무것도 선택하지 않을지(False)입니다. 반환값은 Boolean으로, 이미 편집 중이거나 편집 모드 전환에 성공하면 True, 그렇지 않으면 False입니다. 셀이 읽기 전용이면 False가 돌아오니, 그 뒤에 EditingControl을 쓰는 코드라면 반환값을 확인해 두는 게 안전합니다.

문서에 정리된 예외는 다음과 같습니다.

예외 발생 조건
InvalidOperationException CurrentCell이 유효한 셀로 지정돼 있지 않을 때, 또는 CellBeginEdit 이벤트 처리기 안에서 이 메서드를 호출했을 때
InvalidCastException 셀의 EditType이 Control에서 파생된 형식이 아니거나 IDataGridViewEditingControl을 구현하지 않을 때
Exception 편집할 셀 값을 초기화하지 못했는데 DataError 이벤트 처리기가 없거나, 처리기에서 ThrowException을 True로 둔 경우. 보통 FormatException으로 캐스팅할 수 있습니다.

행이 하나도 없는 그리드에서 F2를 누르면 CurrentCell이 Nothing이라 첫 번째 예외가 나기 쉽습니다. If DataGridView1.CurrentCell Is Nothing Then Exit Sub 같은 확인을 앞에 넣어 두면 깔끔합니다.

붙일 때 확인할 것

두 코드 모두 메서드 선언에 Handles 절이 없습니다. 디자이너에서 이벤트를 연결하지 않았다면 폼 로드에서 AddHandler DataGridView1.KeyDown, AddressOf DataGridView_KeyDownd처럼 직접 연결해야 실행됩니다.

sender를 Object 그대로 두고 sender.BeginEdit(...)를 부르는 건 늦은 바인딩이라 Option Strict Off에서만 컴파일됩니다. Option Strict On인 프로젝트라면 이렇게 형변환해서 쓰면 됩니다.

        Dim dgv As DataGridView = DirectCast(sender, DataGridView)
        If dgv.BeginEdit(False) Then
            Dim tb As TextBox = TryCast(dgv.EditingControl, TextBox)
            If tb IsNot Nothing Then tb.Select(tb.Text.Length, 0)
        End If

TryCast를 쓴 이유는 콤보박스 열이나 체크박스 열에서는 편집 컨트롤이 텍스트박스가 아니기 때문입니다. 원본 코드처럼 DataGridViewTextBoxEditingControl 형식 변수에 바로 넣으면 그런 열에서 F2를 눌렀을 때 형변환 오류가 납니다. DataGridViewTextBoxEditingControl은 TextBox를 상속하므로 TextBox로 받아도 Select를 그대로 쓸 수 있습니다.

같은 방식으로 Enter 키를 눌렀을 때 아래가 아니라 오른쪽 셀로 이동하게 하거나, 특정 열에서만 전체 선택이 되게 하는 식으로 KeyDown 안에서 열 인덱스를 보고 분기해 응용할 수 있습니다.