顯示具有 程式設計技巧 標籤的文章。 顯示所有文章
顯示具有 程式設計技巧 標籤的文章。 顯示所有文章

2014年5月14日 星期三

[學習] DataGridView 設置 Column 顯示的格式為百分比

目的:
將Column的格式設置為百分比!

法一:    
DataGridView1.DataSource = dt
DataGridView1.Columns("新增次數").Visible = False
DataGridView1.Columns("供應商成交率").DefaultCellStyle.Format = "p"
DataGridView1.Columns("集團成交率").DefaultCellStyle.Format = "p"

法二:

Private Sub DataGridView1_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
      If Me.DataGridView1.Columns(e.ColumnIndex).Name = "供應商成交率" OrElse Me.DataGridView1.Columns(e.ColumnIndex).Name = "集團成交率" Then
          If e.Value IsNot Nothing Then
              e.Value = e.Value * 100 & "%"
          End If
      End If
End Sub

結果:
(1)原始資料


(2)顯示資料







參考:
DataGridView中显示百分比
DataGridView.CellFormatting 事件
格式化 Windows Form DataGridView 控制項中的資料
[C#] 字串輸出格式
string.Format 格式參數
23654.3654          Result
N0 取整數           23654
N1 取一位數       23654.3
N2 取二位數       23654.36(若有進位就 23654.37)
以此類推
DataGridView 控制項 (Windows Form)

[ASP.NET] Gridview 欄位輸出格式 DataFormatString
http://msdn.microsoft.com/zh-tw/library/vstudio/f9x2790s(v=vs.100).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1

2013年8月8日 星期四

[技巧] DataGridViewComboBoxCell 取得 Value 的值

程式碼:
                DataGridView1.AutoGenerateColumns = False
                Dim cmb As New DataGridViewComboBoxColumn()
                cmb.HeaderText = "供應商簡稱"
                cmb.Name = "供應商簡稱"
                cmb.DataPropertyName = "供應商別"
                cmb.DisplayMember = "供應商簡稱"
                cmb.ValueMember = "供應商編號"
                cmb.DataSource = dt供應商
                DataGridView1.Columns.Insert(4, cmb)

原因:
假設某個Cell的 DisplayValue 為 "男", Value 為 "1"
當我們取用 DataGridView1(x,y).Value 時,
則其值為 ValueMember "1"
當我們要取值為男時為如何?

解決:
DataGridView1(col, row).FormattedValue.ToString

參考:
Getting Selected Text of combobox in datagridview
How to get the TEXT of Datagridview Combobox selected item?
DataGridView 控制項 (Windows Form)
請問DataGridViewComboBoxColumn 要如何取到改變selecteditem 後的值或文字

ProcessCmdKey方法让DataGridView按Enter回车键转到下一列的格
(讓ComboBoxColumn在下拉選項時, 解決出現二種模式...)

2013年7月30日 星期二

[除錯] TabControl 內的控制項 與 資料繫結 DataBindings, 卻檢查出空白值!

原因:
1.



控制項(TextBox、ComboBox, etc...) 在TabControl時, 且有資料繫結DataBinding(確實有值)
當儲存(檢查控制項是否空白)時, 卻會檢查出此控制項為空白!

2.
tabPage1有DataGridView綁定 bindingsource
當tabPage2為顯示頁時,此時執行 bindingsource.CancelEdit()
則會引發錯誤:
System.ArgumentOutOfRangeException 未處理
  Message=提供的資料列索引超出範圍。
參數名稱: rowIndex
  Source=System.Windows.Forms
  ParamName=rowIndex
  StackTrace:
       於 System.Windows.Forms.DataGridViewRowCollection.GetRowState(Int32 rowIndex)


解決:how to force all controls on all tab pages of a tab control to load/createhandle at once?
1.
//讓不同的tabPage的Control可以load DataBinding資料
foreach (var v in tabControl1.Controls.OfType<TabPage>())
     v.Show();

2.
執行程式時, 需每個TABPAGE都(手動)點過!

3.
        TabPage1.Show()
        TabPage2.Show()
        TabPage3.Show()
        TabPage4.Show()

4.
dgvM.DataSource = null;
bdNavi.BindingSource.RemoveCurrent();(或 bdNavi.BindingSource.CancelEdit();)  <--- 出錯點
bdNavi.BindingSource.ResetBindings(false);
dgvM.DataSource = bs;

2013年5月21日 星期二

[學習] 四捨五入

[SQL]
select round(1.5446,2)
1.5400

select round(round(1.5446,3),2)
1.5500

select CAST(1.5446 AS decimal(9,2))
1.54

select CAST(1.546 AS decimal(9,2))
1.55

*資料型態decimal
  -生產數、工作分鐘 

統計數 =  Convert(Decimal(18,4) , 生產數 / 工作分鐘) * 60

[VB]
Module Module1
    Sub Main()
        Console.WriteLine((0.46).ToString("0"))
        'Console.WriteLine((1.45).ToString("0.0"))
        Console.WriteLine((0.5).ToString("0"))

        Console.WriteLine((0.46).ToString("f"))
        Console.WriteLine((0.5).ToString("f"))

        Console.WriteLine((4.625).ToString("0.00"))
        Console.WriteLine((4.645).ToString("0.00"))

        Console.WriteLine((4.625).ToString("f2"))
        Console.WriteLine((4.645).ToString("f2"))

        'Console.WriteLine((1.5).ToString("0"))
        Dim a As Double = 0.45
        Dim b As Decimal = 0.46
        'Dim c As Decimal = 4.625
        Console.WriteLine(Math.Round(a, 0, MidpointRounding.AwayFromZero))
        Console.WriteLine(Math.Round(b, 0, MidpointRounding.AwayFromZero))
        Console.WriteLine(Math.Round(4.625, 2, MidpointRounding.AwayFromZero))
        Console.WriteLine(Math.Round(CDec(4.645), 2, MidpointRounding.AwayFromZero))
        Console.Read()
    End Sub
End Module

-----------------

1. 整數以下四捨五入
     int(46410*0.05+0.5)=2321

2. 例 : 12.346 四捨五入至小數點以下一位
     int(12.346*10+0.5)/10=12.3

3. 例 : 12.346 四捨五入至小數點以下二位
     int(12.346*100+0.5)/100=12.35

參考:
浮點數計算結果更接近正解? 算錢用浮點,遲早被人扁

access中含四舍五入取值方法的查询sql语句
正確的四捨五入

[WIKI]數值簡化規則
C# Round (四捨五入) 使用 ToString()
利用VB.NET Format函数实现四舍五入功能
格式化输出-数字.ToString
c#中的常用ToString()方法总结
好用的string.Format或ToString()格式化字串的方法
[C#]簡單快速將各種數值字數轉成數字(string to int)
C#,double和decimal数据类型以截断的方式保留指定的小数位数

 '四捨五入
Public Function Round45(ByVal dblValue As Double) As Long
     Round45 = Fix(dblValue + 0.5 * Math.Sign(dblValue))
End Function

C#沒有四捨五入?只有五捨六入的涵數?
只要試試4.625與4.645兩個都對, 那才是真的對了

decimal 小數點位數 四捨五入
[C#]無條件進位,無條件捨去及四捨五入寫法

[ACCESS]單精準數運算Round取到小數位數問題
Round 函數

How To Implement Custom Rounding Procedures

2013年5月17日 星期五

[技巧] DataGridView 當 ReadOnly = True 則跳下一欄位... & 類似VBA的TabStop功能...


用途:
DataGridView 遇到 ReadOnly 則跳過... (不停留 StopTab) 加強版
當設置某些欄位設置 CellStop ,則按 Enter/Tab 時直接跳過
但當用滑鼠點選時依然可以編輯,因為其 ReadOnly = False
如粉紅標記處

程式:
   Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
        '當按enter鍵時 執行tab鍵 -> 實現換行 '不過若是button鍵 就不能tab喔 應該是要Enter事件
        If keyData = Keys.Enter Then
            If Me.ActiveControl.Name = "DataGridView1" Then
                    Return SelectNextCell() 
            End If
        End If

        If keyData = Keys.Tab Then
            If Me.ActiveControl.Name = "DataGridView1" Then
                    Return SelectNextCell() 
            End If
        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 (CellStop.IndexOf(DataGridView1.Columns(column).Name) <> -1 _
                    OrElse 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
        DataGridView1.CurrentCell = DataGridView1(column, row)
        Return True
    End Function

Dim CellStop As New ArrayList()
Private Sub DataGridView1_SelectionChanged(ByVal sender As Object, ByVal e As
        Me.CellStop.Clear()
        If Me.DataGridView1.CurrentRow.Cells("產品編號").Value.ToString.Split("-")(0) = "0" Then
            Me.CellStop.Add("牌價編號")
            Me.CellStop.Remove("尺寸規格名稱")
            Me.CellStop.Remove("材質全名")
        Else
            Me.CellStop.Remove("牌價編號")
            Me.CellStop.Add("尺寸規格名稱")
            Me.CellStop.Add("材質全名")
        End If
End Sub

=========================
備註:
1.
紫色標記處,為避免發生 "無法將目前的儲存格設定為不可見的儲存格" 的錯誤。

 2.
DataGridView 覆寫 ProcessDialogKey 及 ProcessDataGridViewKey 並成一個元件。
而黃色標記部份,是為了防止在編輯狀態下鍵入 Tab(Right / Left) 鍵 ,
避免在 ComBoBoxCell 時,在選擇期間鍵入此三鍵,而產生最左邊的RowHead
其三角形變成(並一直處於)編輯狀態(筆的形狀)...


Public Class mydgv
    Inherits DataGridView
    <System.Security.Permissions.UIPermission( _
        System.Security.Permissions.SecurityAction.LinkDemand, _
        Window:=System.Security.Permissions.UIPermissionWindow.AllWindows)> _
    Protected Overrides Function ProcessDialogKey( _
        ByVal keyData As Keys) As Boolean

        ' Extract the key code from the key value.
        Dim key As Keys = keyData And Keys.KeyCode

        ' Handle the ENTER key as if it were a RIGHT ARROW key.
        If key = Keys.Enter Then
            Return Me.ProcessRightKey(keyData)
        End If

        If (key = Keys.Tab) AndAlso CurrentCell.IsInEditMode Then
            Return False
        End If

        Return MyBase.ProcessDialogKey(keyData)
    End Function

    <System.Security.Permissions.SecurityPermission( _
        System.Security.Permissions.SecurityAction.LinkDemand, Flags:= _
        System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)> _
    Protected Overrides Function ProcessDataGridViewKey( _
        ByVal e As System.Windows.Forms.KeyEventArgs) As Boolean

        ' Handle the ENTER key as if it were a RIGHT ARROW key.
        If e.KeyCode = Keys.Enter Then
            Return Me.ProcessRightKey(e.KeyData)
        End If

        If (e.KeyCode = Keys.Left OrElse e.KeyCode = Keys.Right) AndAlso CurrentCell.IsInEditMode Then
            Return False
        End If

        Return MyBase.ProcessDataGridViewKey(e)
    End Function
End Class

[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;
    }
  }
}

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

DataGridView 编辑回车事件
跳到某一格...
.Net 2.0 DataGridView中键盘事件处理方法
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 方法

2013年5月6日 星期一

[技巧] DataGridViewComboBoxColumn 資料繫結(數據綁定) 驗證(判斷)值是否為繫結內的值 + 可手動輸入(自動篩選)

簡述:
DataGridViewComboBoxColumn 來源為資料庫dt (OR 自定義的DataTable)


Dim columnProvider As New DataGridViewComboBoxColumn()
        columnProvider.HeaderText = "供應商"
        columnProvider.Name = "供應商"
        columnProvider.DataPropertyName = "供應商編號"
        Dim graphics = CreateGraphics()

        columnProvider.DropDownWidth = (From width In (From item As DataRow In dt供應商.Rows _
                                                  Select Convert.ToInt32(graphics.MeasureString(item("供應商簡稱").ToString, Font).Width)) _
                                                  Select width).Max

        columnProvider.DataSource = dt供應商
        columnProvider.DisplayMember = "供應商簡稱"
        columnProvider.ValueMember = "供應商編號"


目的:
讓使用者可透過 "以下" 來篩選資料,但不可以為繫結資料外的值!


Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing


     If TypeOf e.Control Is DataGridViewComboBoxEditingControl Then
            CType(e.Control, ComboBox).DropDownStyle = ComboBoxStyle.DropDown
            CType(e.Control, ComboBox).AutoCompleteSource = AutoCompleteSource.ListItems
            CType(e.Control, ComboBox).AutoCompleteMode = AutoCompleteMode.SuggestAppend

     End If
End Sub


程式: 因為想要把"需要判斷欄位"寫在同一個Sub,因此依這個來解決比較好閱讀!

    Private Sub DataGridView1_CellValidating(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating
        If DataGridView1.Columns(e.ColumnIndex).ReadOnly = True Then
            Exit Sub
        End If

        Dim grid As DataGridView = CType(sender, DataGridView)
        grid.Rows(e.RowIndex).ErrorText = ""

        If grid.Columns(e.ColumnIndex).Name = "供應商" Then
            '判斷是否為dt供應商內的值
            Dim num As Integer = 0
            For Each dr As DataRow In dt供應商.Rows
                If grid.Rows(e.RowIndex).Cells("供應商").EditedFormattedValue.ToString.Trim = dr("供應商簡稱").ToString.Trim Then
                    'MsgBox(dr("供應商簡稱").ToString.Trim)
                    num += 1
                    Exit For
                End If
            Next

            If num = 0 Then

                DataGridView1.Rows(e.RowIndex).ErrorText = _
                "不允許自行輸入, 請重新選擇!!"

                MsgBox("不允許自行輸入, 請重新選擇!!")
                e.Cancel = True
            End If
        End If
    End Sub

另解(1):  透過 CType(sender, ComboBox).SelectedIndex(SelectedItem/SelectedText,etc...) 來判斷!
DataGridViewComboBoxColumn 實現 SelectedIndexChanged 事件
How to get the valuemember from a DataGridViewComboBoxCell
Getting the Selected Value of Combo Box in DataGridView

另解(2):
System.ArgumentException:DataGridViewComboBoxCell 值無效 (2) 之 解決(二)


參考:
DataGridViewComboBoxCell.GetFormattedValue 方法
get value of combobox columns valuemember's value in DataGridView
實作 DataGridViewDropDownColumn
datagridview的combobox控件的添加
真正的DataGridViewComboBoxColumn
DataGridView 控制項 (Windows Form)

DataGridViewComboBoxColumn 可以让用户输入并自动匹配的选项的问题
你指定了ComboBox的DisplayMember和ValueMember后,会按你输入的ValueMember来匹配的,如果输入的如果你说的管理员,它在valueMember中不存在,所以不会选中.这样的话和你设置的就矛盾了,所以应该换种思路,不一定要用comboBox,可以把当前编辑的当元格转换成TextBox,然后在TextBoxChanged里面写,至于下拉列表可以用一个listview来显示,只要把它显示在TextBox的下端坐标值即可.那样根据输入的值,listview自动找匹配的供用户自己选择

ProcessCmdKey方法让DataGridView按Enter回车键转到下一列的格
(讓ComboBoxColumn在下拉選項時, 解決出現二種模式...)

2013年5月2日 星期四

[除錯] 並未將物件參考設定為物件的執行個體 DataGridViewComboBox [debug]

錯誤:
DataGridViewComboBox
並未將物件參考設定為物件的執行個體

程式:

            For Each dgvr As DataGridViewRow In DataGridView1.Rows
                'If dgvr.Index = DataGridView1.RowCount - 1 Then
                '    Exit For
                'End If
                'If dgvr.IsNewRow Then
                '    MsgBox("HAHA")
                '    Exit For
                'End If
                MsgBox(dgvr.Cells("供應商").Value.ToString.Trim)
            Next

解決:
因為 AllowUserToAddRows = True
所以 DGV 會自動 NewRow 出來

而 NewRow 在 for-loop 裡也會算作一份(index)
但實質上是 Nothing 的資料型態
當 loop 到 NewRow 時,便會發生如圖的錯誤

因此在 for-loop 時,要排除掉
可利用黃色方法或綠色方法

DataGridView 控制項 (Windows Form)

2013年4月26日 星期五

[技巧] DataGridView 驗證欄位的資料型態 以及 是否空白

程式:

    Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit

        'DataGridView1.Rows(e.RowIndex).ErrorText = String.Empty
    End Sub

Private Sub DataGridView1_CellValidating(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating

        If e.ColumnIndex >= 10 AndAlso e.ColumnIndex <= 19 Then
            Exit Sub
        End If

        Dim newInteger As Integer
        Dim newDeciaml As Decimal

        Dim grid As DataGridView = CType(sender, DataGridView)
        grid.Rows(e.RowIndex).ErrorText = ""

        If String.IsNullOrEmpty(e.FormattedValue.ToString) Then
            DataGridView1.Rows(e.RowIndex).ErrorText = _
            "不允許空白!!"
            MsgBox("不允許空白")
            e.Cancel = True
        Else If grid.Columns(e.ColumnIndex).Name = "新增次數" OrElse grid.Columns(e.ColumnIndex).Name = "序號" _

           OrElse grid.Columns(e.ColumnIndex).Name = "項次" Then
            If Not Integer.TryParse(e.FormattedValue.ToString(), newInteger) _
                OrElse newInteger < 0 Then
                DataGridView1.Rows(e.RowIndex).ErrorText = _
                "只允許Integer!!"
                MsgBox("只允許Integer")
                e.Cancel = True
            End If
        ElseIf grid.Columns(e.ColumnIndex).Name = "金額" Then
            If Not Decimal.TryParse(e.FormattedValue.ToString(), newDeciaml) Then
                DataGridView1.Rows(e.RowIndex).ErrorText = _
                "只允許Decimal!!"
                MsgBox("只允許Decimal")
                e.Cancel = True
            End If
        End If

    End Sub

參考:
DataGridView: why is CellValidating firing as the grid is filling?
DataGridView.CellValidating 事件,確定使用者只輸入正整數。
DataGridView中数据输入验证
c# DataGridView中的单元格中只能输入数字的解决方法
C#如何在DataGridView控件中验证数据输入
DataGridViews, DataBinding and non validating cell values
[C#]DataGridView欄位驗證只能是數字且不能為空白
WinForm中DataGridView验证单元格输入的是数字
[ADO.NET][WinForm] 限制 DataGridView 輸入字元
DataGridView 控制項 (Windows Form)

判斷是否為數字、整數的正則表達式方法
C#检测字符串是否为正整数

[技巧] DataGridViewComboBoxColumn 實現 SelectedIndexChanged 事件

程式:
Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing

        'If Me.DataGridView1.CurrentCell.OwningColumn.Name = "供應商別" Then
                       Dim comboBox1 As ComboBox = CType(e.Control, ComboBox)
            AddHandler comboBox1.SelectedIndexChanged, _
                New EventHandler(AddressOf ComboBox_SelectedIndexChanged)
        'End If
End Sub

Private Sub ComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
        'do something here
         Dim comboBox1 As ComboBox = CType(sender, ComboBox)
         MsgBox(comboBox1.SelectedValue.ToString)
End Sub

DEBUG:
上面的寫法會引發多次觸發,甚至出現 「並未將物件參考設定為物件的執行個體」錯誤。
如果沒有 If Me.DataGridView1.CurrentCell.OwningColumn.Name = "供應商" Then 
則會造成 DGV 上所有的 DataGridViewComboBoxColumn 都可註冊事件。
因此便需更改如下!

Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
     
        If Me.DataGridView1.CurrentCell.OwningColumn.Name = "供應商" Then
            Dim comboBox1 As ComboBox = CType(e.Control, ComboBox)
            If (comboBox1 IsNot Nothing) Then
                ' Remove an existing event-handler, if present, to avoid
                ' adding multiple handlers when the editing control is reused.
                RemoveHandler comboBox1.SelectedIndexChanged, New EventHandler(AddressOf ComboBox_SelectedIndexChanged)

                ' Add the event handler.
                AddHandler comboBox1.SelectedIndexChanged, New EventHandler(AddressOf ComboBox_SelectedIndexChanged)
            End If
        End If

End Sub


Private Sub ComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
        Dim comboBox1 As ComboBox = CType(sender, ComboBox)
        If CType(sender, ComboBox).SelectedValue IsNot Nothing Then
            MsgBox(comboBox1.SelectedValue.ToString)
        Else
            RemoveHandler comboBox1.SelectedIndexChanged, _
                      New EventHandler(AddressOf ComboBox_SelectedIndexChanged)
        End If
End Sub


參考:
DataGridViewComboBoxEditingControl 類別
DataGridView中comboBox(DataGridViewComboBoxColumn)的事件编写
DataGridViewComboBoxColumn的事件??
如何製作DataGridViewComboBoxColumn SelectedIndexChange
如何给DataGridViewComboBoxColumn写事件
DataGridViewComboBoxColumn的事件
DataGridViewEditingControlShowingEventArgs.Control Property
DataGridViewComboBoxColumn的事件??
DataGridViewComboBoxColumn multiple click SelectedIndexChanged event
如何处理DataGridViewComboBoxCell的SelectedIndexChanged事件?
datagridview 選擇 combobox 值 , 自動帶出資料
commit changed in DataGridView when selection changed in ComboBox
DataGridViewComboBoxColumn Selection Changed

ProcessCmdKey方法让DataGridView按Enter回车键转到下一列的格
(讓ComboBoxColumn在下拉選項時, 解決出現二種模式...)

[技巧] 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 方法