2013年4月26日 星期五

[技巧] DataGridView 遇到 ReadOnly 則跳過... (不停留 StopTab)


    Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
        If keyData = Keys.Enter Then
            If Me.ActiveControl.Name = "DataGridView1" Then
                If CType(Me.ActiveControl, DataGridView).CurrentCell.ReadOnly = True Then
                    SelectNextCell()
                    Return True
                End If
            End If

            'Return MyBase.ProcessCmdKey(msg, keyData)
            SendKeys.Send(vbTab)
            Return True
        End If

        If keyData = Keys.Tab Then
            If Me.ActiveControl.Name = "DataGridView1" Then
                If CType(Me.ActiveControl, DataGridView).CurrentCell.ReadOnly = True Then
                    SelectNextCell() 'SendKeys.Send(Keys.Enter)
                    Return True
                End If
            End If

            Return MyBase.ProcessCmdKey(msg, keyData)
            'SendKeys.Send(vbTab)
            Return True
        End If

        Return MyBase.ProcessCmdKey(msg, keyData)
    End Function


    Public Function SelectNextCell() As Boolean
        Dim row As Integer = DataGridView1.CurrentCell.RowIndex
        Dim column As Integer = DataGridView1.CurrentCell.ColumnIndex
        Dim startingCell As DataGridViewCell = DataGridView1.CurrentCell

        Do
            column += 1
            If column = DataGridView1.Columns.Count Then
                column = 0
                row += 1
            End If
            If row = DataGridView1.Rows.Count Then
                row = 0
            End If
        Loop While DataGridView1(column, row).ReadOnly = True AndAlso DataGridView1(column, row) IsNot startingCell
'Loop While (DataGridView1.Columns(column).Visible = False OrElse DataGridView1(column, row).ReadOnly = True) AndAlso DataGridView1(column, row) IsNot startingCell


        If DataGridView1(column, row) Is startingCell Then
            Return False
        End If

        '這邊要注意起啟的位置,如果Column(0)為ReadOnly,則起啟就設置如下註解! 
        DataGridView1.CurrentCell = DataGridView1(1, row) 'DataGridView1(0, row)


        '如果是要真的讓ReadOnly都直接下一行下一列,則如下的Code才最正確
        DataGridView1.CurrentCell = DataGridView1(column, row)
        Return True
    End Function

[C#]
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace System.Windows.Forms
{
  class MyDataGridView : DataGridView
  {
    protected override bool ProcessDialogKey(Keys keyData)
    {
      if (keyData == Keys.Enter || keyData == Keys.Tab)
      {
        MyProcessTabKey(Keys.Tab);
        return true;
      }
      return base.ProcessDialogKey(keyData);
    }

    protected override bool ProcessDataGridViewKey(KeyEventArgs e)
    {
      if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Tab)
      {
        MyProcessTabKey(Keys.Tab);
        return true;
      }
      return base.ProcessDataGridViewKey(e);
    }

    protected bool MyProcessTabKey(Keys keyData)
    {
      bool retValue = base.ProcessTabKey(Keys.Tab);
      while (this.CurrentCell.ReadOnly)
      {
        retValue = base.ProcessTabKey(Keys.Tab);
      }
      return retValue;
    }
  }
}

備註:
如粉紅標記部份,假設有某欄位的visible=false
則必須在加上條件判斷 "DataGridView1.Columns(column).Visible = False"
此時黃色標記部份即可移除 ,若不加上粉紅標記部份,又沒加上黃色標記部份
則會發生 "無法將目前的儲存格設定為不可見的儲存格" 的錯誤,因為把 DataGridView1.CurrentCell 定為 Visible = False 的 Cell

參考:
鍵盤輸入的運作方式
DataGridView.ProcessDialogKey 方法
DataGridView.ProcessDataGridViewKey 方法
Control.SelectNextControl 方法
Control.GetNextControl 方法

DataGridView 编辑回车事件
跳到某一格...
.Net 2.0 DataGridView中键盘事件处理方法
Protected Overrides Function ProcessCmdKey 
還少了上下左右的判斷,有需要的自己改寫!
Tab to the next cell in a DataGridView
No Tab Stop DataGridView Column
HOW TO AVOID ENTERING READONLY CELLS ON A DATAGRIDVIEW
Bypass read only cells in DataGridView when pressing TAB key
C# Enter轉Tab,讓MultiLine可換行
Up/Down - Arrow function
WM_KEYDOWN message
DataGridView 控制項 (Windows Form)


[C#]DataGridViewのCell移動をEnterで
DataGridViewでEnterキーを押すと隣のセルにフォーカスが移動されるようにする
svn/ trunk/ ExtControls/ 測試專案/ MyDataGridview.cs
Bypass read only cells in DatagridView when pressing TAB key (good)
关于DataGridView中键盘输入时的单元格跳转
svn/ trunk/ PT.Component/ DataGridView.cs
C#的dataGridView控件實現回車右移控制
ProcessCmdKey方法让DataGridView按Enter回车键转到下一列的格

How catch Enter Key on EndEdit of Datagridview
DataGridView.ProcessDataGridViewKey 方法

沒有留言:

張貼留言