タイトル | : Re^5: DataGridViewのComboBoxColumnのコレクションを単一選択にしたい |
記事No | : 5485 |
投稿日 | : 2007/05/15(Tue) 13:08 |
投稿者 | : 魔界の仮面弁士 |
となると、CellValueChanged イベントが妥当でしょう。 e.ColumnIndex と e.RowIndex から、選択された値を取得して、 その値が他の行で既に使われていたら、その行の値をクリアする、と。
たとえば、こんな感じ。 -------------- Public Class Form1
'実験用のダミーデータ生成。このあたりは適当に。 Private Function CreateComboItem() As String() Dim list As New List(Of String) list.Add("") list.Add("Visual Basic") list.Add("C#") list.Add("C++/CLI") list.Add("JScript") list.Add("Delphi") Return list.ToArray() End Function
'説明の都合上、今回はコントロール生成も Form1_Load で行っていますが、 '普通は、デザイン時に設定しておくだけで十分です。 Private WithEvents dataGridView1 As New DataGridView() Private comboColumn1 As DataGridViewComboBoxColumn Private items() As String
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs _ ) Handles MyBase.Load 'コンボボックス列の設定 comboColumn1 = New DataGridViewComboBoxColumn() comboColumn1.DataSource = CreateComboItem()
'グリッドの設定 dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter dataGridView1.Dock = DockStyle.Fill dataGridView1.ColumnHeadersVisible = False dataGridView1.RowHeadersVisible = False dataGridView1.AllowUserToResizeRows = False dataGridView1.AllowUserToResizeColumns = False dataGridView1.AllowUserToAddRows = False dataGridView1.DefaultCellStyle.SelectionBackColor = _ dataGridView1.DefaultCellStyle.BackColor dataGridView1.DefaultCellStyle.SelectionForeColor = _ dataGridView1.DefaultCellStyle.ForeColor dataGridView1.RowCount = 5 dataGridView1.ColumnCount = 1 dataGridView1.Columns.Add(comboColumn1) Controls.Add(dataGridView1)
'おまけ Dim combo As New DataGridViewComboBoxCell() combo.Items.AddRange("犬 猿 雉".Split()) dataGridView1(0, 0) = combo dataGridView1(0, 0).Value = "猿" dataGridView1(0, 1).Style.BackColor = Color.Gold dataGridView1(0, 1).Style.ForeColor = Color.Red dataGridView1(0, 1).Value = "テキスト" dataGridView1(0, 2) = New DataGridViewButtonCell() dataGridView1(0, 2).Value = "ボタン" dataGridView1(0, 3) = New DataGridViewImageCell(False) dataGridView1(0, 3).Value = Me.Icon dataGridView1(0, 4) = New DataGridViewCheckBoxCell() dataGridView1(0, 4).Style.Alignment = DataGridViewContentAlignment.MiddleCenter dataGridView1(0, 4).Value = True End Sub
'ここから本題。 Private Sub dataGridView1_CellValueChanged(ByVal sender As Object, _ ByVal e As DataGridViewCellEventArgs) Handles dataGridView1.CellValueChanged If e.ColumnIndex <> comboColumn1.Index Then Return End If
'選択されたコンボ項目を取得 Dim dgv As DataGridView = DirectCast(sender, DataGridView) Dim value As String = dgv(e.ColumnIndex, e.RowIndex).Value.ToString()
If value = "" Then '未選択状態の時は、特に何もしない Return End If
'他の行の状態を確認 For rowIndex As Integer = 0 To dgv.RowCount - 1 If rowIndex = e.RowIndex Then '自分は除外 Continue For End If Dim cell As DataGridViewCell = dgv(e.ColumnIndex, rowIndex) If Object.Equals(cell.Value, value) Then '同じ値を持つ行があれば、未選択に戻す cell.Value = "" Exit For End If Next End Sub End Class ----------
この場合、重複した他のセルの値がクリアされるのは、コンボボックスから 選択したときではなく、選択後にそのセルからフォーカスが抜けたときです。
もしセルを移動させることなく、項目が選択されるたびに、即座に他の行の値を クリアしたいのであれば、CurrentCellDirtyStateChanged イベントでコミットすれば OK です。
Private Sub dataGridView1_CurrentCellDirtyStateChanged(…… If dataGridView1.CurrentCell.ColumnIndex = comboColumn1.Index Then dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit) End If End Sub
ただ、即座にコミットすると見た目はわかりやすいのですが、それだと困ることもあります。 ドロップダウンからのクリックで選択した場合であれば良いのですが、マウスホイールや 矢印キーで選択した場合には、そのたびに他の行の値が次々とクリアされる結果になるので。
|