トップ回答者
DataGridViewでセルの値を変更したときに、他のセルに自動で値を入力しますが、このときエラーが発生します。

質問
-
サーバー:SQL2003, VB2010 です。
データ変更は、直接DBに書き込むようにしています。
DataGridViewでセルの値を変更したときに、行単位で他のセルに、PC名・入力日を自動で書き込むようにしました。
このときに、エラーが発生します(追加したコンボボックスで発生します)。フォーム内にDataGridViewがあり、そこには複数行のデータが表示されています。
フォームは、売上伝票。 DataGridViewは、その売上伝票内の個別売上品目を表示しています。(必要ならば、関連コード記載します。 私の直前のスレッドにありますが。)
売上品目(DataGridView)のセルには、コンボボックスも追加しています。
データを変更したときに、PC名・入力日も自動記入するようにしています。
現在のコードですと、一行のみ変更しても、DB(サーバー)に書き込むと全行が新しいPC名・入力日になっています。
For -- Nextで回しているからです(DataGridView内で)。で、下記記載のコードを書き、変更行のみに、新しいPC名・入力日を自動記入するようにしました。
テキストボックスは成功しています。(DataGridViewのセルは、テキストボックスなので)
このコードで、変更前の行はそのままで、変更行のみが新しいPC名・入力日になっています。ところが、コンボボックスからの変更は反映されないので、下記掲載コードのようにComboBoxについても、コードを追加しました。DataGridViewのセルは、ComboBoxでないので。
コンボボックスでの変更は、下記エラーが発生します。 コンボボックスでの変更自体は反映されています、新しいPC名・入力日になっていますエラー内容:
DataGridViewで次のエラーが発生;
System.ArgumentException:データソースプロパティを設定したときに、Itemsコレクションを変更することはできません。
場所、System.Windows.Forms.ComboBox.CheckNoDataSource
場所、System.Windows.Forms.DataGridViewComboBoxCell.InitializeEditingControl
場所、System.Windows.Forms.DataGridView.InitializeEditingControl.ValueDataGridViewのコンボボックスでの変更は、一行のみの変更はOKでした。 他の行に移動しなければ、エラー表示しません。 カーソル(マウス)を他の行に移動させると、上記エラー表示します。
コンボボックス選択後、他の行に行く前に、その行の他のテキストボックスを一度選択してから、他の行のコンボボックスに移動するときは、エラー表示しません。
データ変更は、すべてうまくいっています。
解決法を、お教えください。
YKsaila
コードを添付します:
'以下は、DataGridViewでの変更を、行単位で個別に書き込むもの(PC名・入力日について)
Private dataGridViewComboBox As DataGridViewComboBoxEditingControl = Nothing
'EditingControlShowingイベントハンドラ
Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) _
Handles DataGridView1.EditingControlShowing'表示されているコントロールがDataGridViewTextBoxEditingControlか調べる
If TypeOf e.Control Is DataGridViewTextBoxEditingControl Then
Dim dgv As DataGridView = CType(sender, DataGridView)'編集のために表示されているコントロールを取得
Dim tb As DataGridViewTextBoxEditingControl = CType(e.Control, DataGridViewTextBoxEditingControl)
'イベントハンドラを削除
RemoveHandler tb.KeyPress, AddressOf dataGridViewTextBox_KeyPress'該当する列か調べる '
If dgv.CurrentCell.OwningColumn.Name = "Roll" OrElse dgv.CurrentCell.OwningColumn.Name = "Length" _
OrElse dgv.CurrentCell.OwningColumn.Name = "UnitWeight" OrElse dgv.CurrentCell.OwningColumn.Name = "ValuePrice" _
OrElse dgv.CurrentCell.OwningColumn.Name = "Volume" OrElse dgv.CurrentCell.OwningColumn.Name = "UnitPrice" _
OrElse dgv.CurrentCell.OwningColumn.Name = "Amount" OrElse dgv.CurrentCell.OwningColumn.Name = "CostAmount" Then
'下記、CB_ItemNo/CB_Metal_IDは、ComboBoxなので不可!!
'OrElse dgv.CurrentCell.OwningColumn.Name = "CB_Metal_ID" OrElse dgv.CurrentCell.OwningColumn.Name = "CB_ItemNo"
'KeyPressイベントハンドラを追加
AddHandler tb.KeyPress, AddressOf dataGridViewTextBox_KeyPress
End If
End If
'表示されているコントロールがDataGridViewComboBoxEditingControlか調べる
If TypeOf e.Control Is DataGridViewComboBoxEditingControl Then
Dim dgv As DataGridView = CType(sender, DataGridView)'編集のために表示されているコントロールを取得
Me.dataGridViewComboBox = CType(e.Control, DataGridViewComboBoxEditingControl)'イベントハンドラを削除
RemoveHandler Me.dataGridViewComboBox.SelectedIndexChanged, AddressOf dataGridViewComboBox_SelectedIndexChanged'該当する列か調べる
If dgv.CurrentCell.OwningColumn.Name = "CB_Metal_ID" OrElse dgv.CurrentCell.OwningColumn.Name = "CB_ItemNo" Then
'下記二行、上へ移動。
'編集のために表示されているコントロールを取得
'Me.dataGridViewComboBox = CType(e.Control, DataGridViewComboBoxEditingControl)'SelectedIndexChangedイベントハンドラを追加
AddHandler Me.dataGridViewComboBox.SelectedIndexChanged, AddressOf dataGridViewComboBox_SelectedIndexChanged
End If
End IfEnd 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に表示されているテキストボックスのKeyPressイベントハンドラ
Private Sub dataGridViewTextBox_KeyPress(ByVal sender As Object, ByVal e As KeyPressEventArgs)
'SYS_Update_Date(入力日)/PC名を書き込む
Me.DataGridView1.CurrentRow.Cells("SYS_Update_Date").Value = Now
Me.DataGridView1.CurrentRow.Cells("SYS_Computer_ID").Value = GetCpuName()
'上記は、GetCpuName以外に、My.Computer.Name/GetHostName(ホスト名)/Environment.MachineNameでも、可End Sub
'DataGridViewに表示されているコンボボックスの SelectedIndexChangedイベントハンドラ
Private Sub dataGridViewComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
'SYS_Update_Date(入力日)/PC名を書き込む
'Dim computename As String
'computename = GetCpuName()
Me.DataGridView1.CurrentRow.Cells("SYS_Update_Date").Value = Now
Me.DataGridView1.CurrentRow.Cells("SYS_Computer_ID").Value = GetCpuName()
'上記は、GetCpuName以外に、My.Computer.Name/GetHostName(ホスト名)/Environment.MachineNameでも、可End Sub
- 編集済み yksaila 2012年10月28日 15:48
回答
-
DataGridViewで次のエラーが発生;
System.ArgumentException:データソースプロパティを設定したときに、Itemsコレクションを変更することはできません。
掲載されているコード以外がエラーの原因になっていると思います。エラーの意味としては、このコンボボックスの一覧(Items)はDataSourceプロパティに指定されたデータソースから供給されているので、Itemsを直接変更してはいけないということです。
Itemsが直接変更されてしまうと、DataSourceプロパティに指定されているデータソースの中身と一致しなくなってしまうからです。★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク yksaila 2012年10月31日 1:27
-
trapemiyaさんへ
ご回答、ありがとうございます。
あれから、いろいろと勉強してみました。 「Itemsを直接変更してはいけない」という意味も理解できました。
下記2行を省くと、うまくいきます。 当たり前ですね! 指示が空になるんですから。
Me.DataGridView1.CurrentRow.Cells("SYS_Update_Date").Value = Now
Me.DataGridView1.CurrentRow.Cells("SYS_Computer_ID").Value = GetCpuName()よく考えてみれば、”AddHandler Me.dataGridViewComboBox.SelectedIndexChanged”のとき、コンボボックスのItemsを変えようとしているんでした。
というか、このコード群自体が、私の場合は企画倒れで、無意味・無駄でした。
目的は、「ある行のデータを変更したときに、その行のPC名・入力日を自動記入する」、でした。
下記コードのみで(掲載コードは、すべて削除)、DataGridViewのTextBox,ComboBoxの各セル変更時に、PC名・入力日を自動記入できました。
'CellEndEditイベントハンドラ
Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
'SYS_Update_Date(入力日)/PC名を書き込む
Me.DataGridView1.CurrentRow.Cells("SYS_Update_Date").Value = Now
Me.DataGridView1.CurrentRow.Cells("SYS_Computer_ID").Value = GetCpuName()End Sub
なんと、無駄な遠回りをしたのかと、自分でも不思議です。 ま、知らない、経験がない、というのはこういうことなのでしょうね。
こうやって、すこしずつ、言葉を覚えていくしかないみたいです。
再度、ありがとうございました。
YKsaila
すべての返信
-
DataGridViewで次のエラーが発生;
System.ArgumentException:データソースプロパティを設定したときに、Itemsコレクションを変更することはできません。
掲載されているコード以外がエラーの原因になっていると思います。エラーの意味としては、このコンボボックスの一覧(Items)はDataSourceプロパティに指定されたデータソースから供給されているので、Itemsを直接変更してはいけないということです。
Itemsが直接変更されてしまうと、DataSourceプロパティに指定されているデータソースの中身と一致しなくなってしまうからです。★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
- 回答としてマーク yksaila 2012年10月31日 1:27
-
trapemiyaさんへ
ご回答、ありがとうございます。
あれから、いろいろと勉強してみました。 「Itemsを直接変更してはいけない」という意味も理解できました。
下記2行を省くと、うまくいきます。 当たり前ですね! 指示が空になるんですから。
Me.DataGridView1.CurrentRow.Cells("SYS_Update_Date").Value = Now
Me.DataGridView1.CurrentRow.Cells("SYS_Computer_ID").Value = GetCpuName()よく考えてみれば、”AddHandler Me.dataGridViewComboBox.SelectedIndexChanged”のとき、コンボボックスのItemsを変えようとしているんでした。
というか、このコード群自体が、私の場合は企画倒れで、無意味・無駄でした。
目的は、「ある行のデータを変更したときに、その行のPC名・入力日を自動記入する」、でした。
下記コードのみで(掲載コードは、すべて削除)、DataGridViewのTextBox,ComboBoxの各セル変更時に、PC名・入力日を自動記入できました。
'CellEndEditイベントハンドラ
Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
'SYS_Update_Date(入力日)/PC名を書き込む
Me.DataGridView1.CurrentRow.Cells("SYS_Update_Date").Value = Now
Me.DataGridView1.CurrentRow.Cells("SYS_Computer_ID").Value = GetCpuName()End Sub
なんと、無駄な遠回りをしたのかと、自分でも不思議です。 ま、知らない、経験がない、というのはこういうことなのでしょうね。
こうやって、すこしずつ、言葉を覚えていくしかないみたいです。
再度、ありがとうございました。
YKsaila