3

セットアップ: 2 つの DataGridView があり、それぞれがカスタム ビジネス オブジェクトの BindingList<> にバインドされています。これらのグリッドには、そのグリッド内のすべての行の数学的合計を含む特別な行があります。この特別な行は、BindingList<> 内の対応する特別なオブジェクトを反映しています (これが追加される行ではないことがわかるように指定します)。 DGV に追加されますが、オブジェクトは BindingList<> に追加されます)。

エラー: 定期的に、Totals Row オブジェクトを見つけて BindingList<> (したがって DGV) から削除する必要があります。これを行うために使用していた元のコードは次のとおりです。

private void RemoveTotalRow()
  {
     for (int i = UnderlyingGridList.Count - 1; i >= 0; i--)
     {
        if (UnderlyingGridList[i].IsTotalRow) UnderlyingGridList.RemoveAt(i);  
     }
  }

(それほど重要ではありませんが、すべてのレコードを繰り返し表示しているのは、誤って合計行が複数になる可能性を防ぐためです)。このコードは、2 つのグリッドのいずれかに対して、すべての状況で問題なく動作します。ただし、2 番目のグリッドでは、RemoveAt メソッドが呼び出されると次のエラーが発生します。

The following exception occurred in the DataGridView:  System.IndexOutOfRangeException: Index 5 does not have a value.    at System.Windows.Forms.CurrencyManager.get_Item(Int32 index)    at System.Windows.Forms.DataGridView.DataGridViewDataConnection.GetError(Int32 rowIndex)  To replace this default dialog please handle the DataError event.

...ここで、「5」は合計行のインデックスです。 私はこの質問を見つけましたが、これは基本的に同じですが、受け入れられた答えは次のいずれかです: 1) 基になるリストを使用しないでください。上記のコード例の最も内側のメソッド呼び出しを次のように置き換えて、#2 を試しました。

if (UnderlyingGridList[i].IsTotalRow) brokenDataGrid.Rows.RemoveAt(i);

これは同じエラーをスローします。 変更後に再バインドすることを提案するこの質問も見つけました - ただし、このコードは1秒に1回呼び出される可能性があり、リストのデータが多すぎるとグリッドが使用できなくなるため、これは現実的ではありません(私はこれを知っています)悪い経験から)。

グリッドの DataError イベントを処理することもできますが、1 分間に 100 万個のエラーが発生しないようにしたいと考えています。どんな助けでも大歓迎です。

4

2 に答える 2

2

これは奇妙な一連の状況でした...しかし、ここに行きます:

1) 問題のグリッドには、SelectionChanged イベントが定義されており、その中で 2 行のコードが呼び出されます。

Grid.ClearSelection(); 
Grid.Refresh(); 

これらがここにあるのは、実際には行が選択されていないのに、選択された行があるように見えるようにグリッドを偽装しているためです。これにより、グリッドの外観をカスタマイズできます。

2)私の質問のコードをトリガーするイベントは、グリッド のソートイベントです。

ステップ 3 と 4 は私の憶測ですが、私のテストでは理論が支持されているようです

3) Grid.Sorted イベントは、明らかにこの Grid.SelectionChanged イベントもトリガーします。

4) グリッドは現在、グリッドを更新し、同時に合計行を削除しようとしています。したがって、ブレークポイントは、実際には機能しない場合でも、機能するはずのように見えます。

上記のイベントから Grid.Refresh() メソッド呼び出しを削除すると、問題が完全に修正されます。作業中のグリッドの Grid.SelectionChanged イベントを調べたところ、Refresh() ではなく、ClearSelection() メソッドのみが呼び出されていることがわかりました。

ここのスレッドと C# チャットで助けてくれた人に感謝します!

于 2011-05-18T15:27:13.840 に答える
1

質問をオーバーフローさせてください。これでしょうか:

for (int i = UnderlyingGridList.Count - 1; i >= 0; i--)

これになる必要があります:

for (int i = UnderlyingGridList.Count - 1; i >= 0; i--)
i+=1

これが短い例です。DataGridView(2列)と2つのボタンを追加するだけです。VB.Netです。

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        Me.Button1.Text = "Create"
        Me.Button2.Text = "Remove"

        Me.DataGridView1.AllowUserToAddRows = False
    End Sub

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        For i As Integer = 0 To 99
            Me.DataGridView1.Rows.Add("Hello", DateTime.Now)
        Next
    End Sub

    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        Dim i As Integer = Me.DataGridView1.Rows.Count - 1
        Do
            If Me.DataGridView1.AllowUserToAddRows = False Then
                If i < 0 Then Exit Do
                Me.DataGridView1.Rows.RemoveAt(i - 0)
            Else
                If i < 1 Then Exit Do
                Me.DataGridView1.Rows.RemoveAt(i - 1)
            End If
            i -= 1
        Loop
    End Sub
End Class

Me.DataGridView1.AllowUserToAddRows=Falseに注意してください

于 2011-05-18T14:04:20.293 に答える