DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DataGridView内の2つのComboBoxを連携させたい

環境/言語:[windowsXP、VB.net、NET Framework4.0]
分類:[.NET]

VB.net初心者です。よろしくお願いいたします。
《環境》SQLServer2008、VB2010


DataGridView内にコンボボックスを2つ配置し、
片方のコンボボックス(Combo_A)の値を変更されたら、
もう片方のコンボボックス(Combo_B)の選択肢を変更するような
プログラミングを行おうとしています。

こちらの掲示板を参考にし、
(http://dobon.net/vb/dotnet/datagridview/selectedindexchanged.html)
コンボボックスのイベントにてCombo_Bの選択肢が変更にできるよう
プログラミングすることができました。

しかし、いったんCombo_A、Combo_Bの入力を行った後、
再びCombo_Aの修正を行った際に、以下のエラーが発生しました。
「DataGridViewで次の例外が発生しました
System.ArgumentException: DataGridViewComboBoxCellの値が有効ではありません。」
エラーが発生した箇所は、フォームが表示される際に起こっています。
ちなみにF8などで、1行ずつステップさせてみましたが、
エラーが自分で書いたソース上で起こらないため、
どこが悪いのかさっぱりわかりません。


原因として考えられそうなことがあれば
教えていただけませんでしょうか?
■No30915に返信(おださとさんの記事)

設定しようとしているリスト内にvalueの値が含まれないからとか。

リスト設定前にValueをDBNull.Valueに設定すると良いかも。
■No30916に返信(shuさんの記事)
> ■No30915に返信(おださとさんの記事)
>
> 設定しようとしているリスト内にvalueの値が含まれないからとか。
>
> リスト設定前にValueをDBNull.Valueに設定すると良いかも。

ご助言ありがとうございます。
コンボボックスの値の設定が悪いのであれば、
一回目でエラーになると思われますので、
大丈夫ではないかと思います。

なお、Combo_Bのリストはデータソース(DictionaryEntryを使用)にて
設定しており、エラー直前にはデータソースへ値がセットされていることを
確認しましたので、違う理由にてエラーが発生しているのではないかと思います。


Combo_Aの値を選択

Combo_Bのリストをプログラムによって設定

Combo_Bの値を選択

Combo_Aに、前回選択した値とは違う値を選択

エラー発生
■No30919に返信(おださとさんの記事)

> Combo_Aの値を選択
> ↓
> Combo_Bのリストをプログラムによって設定
> ↓
> Combo_Bの値を選択
この値を例えばValueBとすると

> ↓
> Combo_Aに、前回選択した値とは違う値を選択
この選択により作成されるCombo_BのリストにValueBが
含まれていない

ということですが、どうですか?
■No30920に返信(shuさんの記事)
> ■No30919に返信(おださとさんの記事)
>
>>Combo_Aの値を選択
>>↓
>>Combo_Bのリストをプログラムによって設定
>>↓
>>Combo_Bの値を選択
> この値を例えばValueBとすると
>
>>↓
>>Combo_Aに、前回選択した値とは違う値を選択
> この選択により作成されるCombo_BのリストにValueBが
> 含まれていない
>
> ということですが、どうですか?
>

とりあえず、以下のようなプログラムにしてみましたが、
だめでした。
入れるところが間違ってますでしょうか?

  'データグリッドビューのコンボボックスの値を変更した際のイベント
Private Sub DataGridViewComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim scn As SqlClient.SqlConnection = New SqlClient.SqlConnection("Data Source=RANAWAY-PC\ranawaydb;Integrated Security=True")
Dim sAdp As SqlClient.SqlDataAdapter
Dim dSet As DataSet = New DataSet
Dim dTbl As DataTable
Dim I As Integer
Dim w_list1 As New ArrayList()
Dim w_str As DataGridViewComboBoxEditingControl = CType(sender, DataGridViewComboBoxEditingControl)
Dim w_X As Integer
Dim w_Y As Integer

w_X = Me.dgv_TBL_SUPPLEMENTARYINFO.CurrentCell.ColumnIndex
w_Y = Me.dgv_TBL_SUPPLEMENTARYINFO.CurrentCell.RowIndex
dgv_TBL_SUPPLEMENTARYINFO(w_X, w_Y).Value = DBNull.Value ←教えていただいた分

'コンボボックス表示
'情報種類をDBから取得
sAdp = New SqlClient.SqlDataAdapter("SELECT Key1, Text1 FROM TBL_WIDEUSEMASTER WHERE (MasterID = 'IT1') AND (Text2 = '" & w_str.SelectedItem & "') AND (StartDate < CONVERT(VARCHAR, GETDATE(), 111)) AND (FinishDate >= CONVERT(VARCHAR, GETDATE(), 111)) ORDER BY DisplayRanking", scn)

sAdp.Fill(dSet, "情報種類")
dTbl = dSet.Tables("情報種類")

    'リストをセット
w_list1.Clear()
For I = 0 To dTbl.Rows.Count - 1
w_list1.Add(New DictionaryEntry(dTbl.Rows.Item(I).Item(0).ToString, dTbl.Rows.Item(I).Item(1).ToString))
Next
Me.cmb_tab5_InfoType.DataSource = w_list1
Me.cmb_tab5_InfoType.DisplayMember = "Value"
Me.cmb_tab5_InfoType.ValueMember = "Key"
End Sub

ちなみに、ご指摘の件は確かに含まれておりません。
>> Combo_Aの値を選択
>> ↓
>> Combo_Bのリストをプログラムによって設定
>> ↓
>> Combo_Bの値を選択
>この値を例えばValueBとすると
>> ↓
>> Combo_Aに、前回選択した値とは違う値を選択
>この選択により作成されるCombo_BのリストにValueBが
>含まれていない

>ということですが、どうですか?
■No30921に返信(おださとさんの記事)

> dgv_TBL_SUPPLEMENTARYINFO(w_X, w_Y).Value = DBNull.Value ←教えていただいた分
これはSelectedIndexChangedが発生したセルでこれからリストを設定するセルではない気がしますが、どうでしょう?

> Me.cmb_tab5_InfoType.DataSource = w_list1
> Me.cmb_tab5_InfoType.DisplayMember = "Value"
> Me.cmb_tab5_InfoType.ValueMember = "Key"
これのcmb_tab5_InfoTypeが何を表しているのか分かりませんがこれはもしかして列の情報(DataGridViewColumn)ではないですか?


以下、サンプルです。
2列(Column1,Column2)で両方ともコンボボックスのDataGridViewを配置してあります。
1列目は3項目固定で設定してあります。
★の箇所がDBNull.Valueに設定している箇所です。ここをコメントアウトして
1列目を選んで2列目を"a1"を選べば1列目を変更しても例外が発生しませんが
"a1"以外を選んでから1列目を変更すると例外が発生します。
☆の箇所をColumn2.DataSource =lstとすると該当行以外で"a1"が選ばれていると例外が発生します。例外が発生しない場合でも他の行のリストも変更されてしまいます。

Private dataGridViewComboBox As DataGridViewComboBoxEditingControl = Nothing

Private Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
    '表示されているコントロールがDataGridViewComboBoxEditingControlか調べる
    If TypeOf e.Control Is DataGridViewComboBoxEditingControl Then
        Dim dgv As DataGridView = CType(sender, DataGridView)

        '該当する列か調べる
        If dgv.CurrentCell.ColumnIndex = 0 Then
            '編集のために表示されているコントロールを取得
            Me.dataGridViewComboBox = _
                CType(e.Control, DataGridViewComboBoxEditingControl)
            'SelectedIndexChangedイベントハンドラを追加
            AddHandler Me.dataGridViewComboBox.SelectedIndexChanged, _
                AddressOf dataGridViewComboBox_SelectedIndexChanged
        End If
    End If
End Sub

'CellEndEditイベントハンドラ
Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, _
        ByVal e As DataGridViewCellEventArgs) _
        Handles DataGridView1.CellEndEdit
    'SelectedIndexChangedイベントハンドラを削除
    If Not (Me.dataGridViewComboBox Is Nothing) Then
        RemoveHandler Me.dataGridViewComboBox.SelectedIndexChanged, _
            AddressOf dataGridViewComboBox_SelectedIndexChanged
        Me.dataGridViewComboBox = Nothing
    End If
End Sub

'DataGridViewに表示されているコンボボックスの
'SelectedIndexChangedイベントハンドラ
Private Sub dataGridViewComboBox_SelectedIndexChanged(ByVal sender As Object, _
        ByVal e As EventArgs)
    '選択されたアイテムを表示
    Dim cb As DataGridViewComboBoxEditingControl = _
        CType(sender, DataGridViewComboBoxEditingControl)
    Dim lst As New List(Of String)
    Select Case cb.SelectedIndex
        Case 0
            lst.AddRange({"a1", "a2", "a3"})
        Case 1
            lst.AddRange({"a1", "b2", "b3"})
        Case 2
            lst.AddRange({"a1", "c2", "c3"})
    End Select

    Dim cell = DirectCast(DataGridView1(1, cb.EditingControlRowIndex), DataGridViewComboBoxCell)
    cell.Value = DBNull.Value   '<--- ★
    cell.DataSource = lst    '<--- ☆
End Sub
上記方法にてDBnull.valueを設定してみましたが、
一回目の選択を行った時点で同じエラーが発生しました。

とりあえずdatagridviewでは、修正を行わないような制限をかけ、
別フォームにて修正を実施するようやってみます。
(別フォームでは、同様のコンボボックスの連携が成功しているので・・・)

shuさんには、何日にもわたってご助言頂きありがとうございました。
大変勉強になりました。
機会がありましたら、これからもよろしくお願いいたします。
■No30923に返信(おださとさんの記事)

> 一回目の選択を行った時点で同じエラーが発生しました。
提示コードはこちらで動いたので不思議ですが原因はたぶん変わらないのでは
と思います。


> とりあえずdatagridviewでは、修正を行わないような制限をかけ、
> 別フォームにて修正を実施するようやってみます。
> (別フォームでは、同様のコンボボックスの連携が成功しているので・・・)
>
それも1つの方法だと思います。DataGridView内ではない通常のコンボボックスならリストにない場合の処理は自動で行われるので大丈夫です。


> shuさんには、何日にもわたってご助言頂きありがとうございました。
> 大変勉強になりました。
こちらが言いたかったことが伝わったのか不明瞭なのが残念ですが、
他の方法により解決しそうで良かったです。

DOBON.NET | プログラミング道 | プログラミング掲示板