none
DataGridViewでセルの値を変更したときに、他のセルに自動で値を入力しますが、このときエラーが発生します。 RRS feed

  • 質問

  • サーバー: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.Value

    DataGridViewのコンボボックスでの変更は、一行のみの変更は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 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に表示されているテキストボックスの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
    2012年10月28日 6:31

回答

  • DataGridViewで次のエラーが発生;
    System.ArgumentException:データソースプロパティを設定したときに、Itemsコレクションを変更することはできません。

    掲載されているコード以外がエラーの原因になっていると思います。エラーの意味としては、このコンボボックスの一覧(Items)はDataSourceプロパティに指定されたデータソースから供給されているので、Itemsを直接変更してはいけないということです。
    Itemsが直接変更されてしまうと、DataSourceプロパティに指定されているデータソースの中身と一致しなくなってしまうからです。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク yksaila 2012年10月31日 1:27
    2012年10月30日 6:22
    モデレータ
  • 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


    • 回答としてマーク yksaila 2012年10月31日 1:26
    • 編集済み yksaila 2012年10月31日 1:29
    2012年10月31日 1:25

すべての返信

  • DataGridViewで次のエラーが発生;
    System.ArgumentException:データソースプロパティを設定したときに、Itemsコレクションを変更することはできません。

    掲載されているコード以外がエラーの原因になっていると思います。エラーの意味としては、このコンボボックスの一覧(Items)はDataSourceプロパティに指定されたデータソースから供給されているので、Itemsを直接変更してはいけないということです。
    Itemsが直接変更されてしまうと、DataSourceプロパティに指定されているデータソースの中身と一致しなくなってしまうからです。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク yksaila 2012年10月31日 1:27
    2012年10月30日 6:22
    モデレータ
  • 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


    • 回答としてマーク yksaila 2012年10月31日 1:26
    • 編集済み yksaila 2012年10月31日 1:29
    2012年10月31日 1:25