0

次のように、プログラムで DataGridView に列を挿入しています (つまり、データ テーブル/データベースにバインドされていません)。

int lastIndex = m_DGV.Columns.Count - 1;  // Count = 4 in this case
DataGridViewTextBoxColumn col = (DataGridViewTextBoxColumn)m_DGV.Columns[lastIndex];
m_DGV.Columns.RemoveAt(lastIndex);
m_DGV.Columns.Insert(insertIndex, col);  // insertIndex = 2

この方法を使用すると、列が視覚的に順不同であることがわかりました。回避策は、後で列の DisplayIndex プロパティを手動で設定することです。このコードを追加すると「修正」されますが、なぜこのように動作するのかわかりません。

Console.Write(m_DGV.Columns[0].DisplayIndex); // Has value of 0
Console.Write(m_DGV.Columns[1].DisplayIndex); // Has value of 1
Console.Write(m_DGV.Columns[2].DisplayIndex); // Has value of 3
Console.Write(m_DGV.Columns[3].DisplayIndex); // Has value of 2
col.DisplayIndex = insertIndex;
Console.Write(m_DGV.Columns[0].DisplayIndex); // Has value of 0
Console.Write(m_DGV.Columns[1].DisplayIndex); // Has value of 1
Console.Write(m_DGV.Columns[2].DisplayIndex); // Has value of 2
Console.Write(m_DGV.Columns[3].DisplayIndex); // Has value of 3

余談ですが、私のグリッドは列数を動的に増やすことができます。チャンクで成長させたかったので、各挿入で列の割り当て (および関連する初期化) は必要ありませんでした。「新しい」各列は、未使用の列を最後から取得し、目的の位置に挿入して表示することで追加されます。

4

3 に答える 3

2

いくつかのアイデアがあります。

  1. コレクション内のインデックスではなく、一意の名前で列をアドレス指定するのはどうですか? 彼らはまだ名前を持っていないかもしれませんが、何か意味のある名前を付ければ、誰が誰であるかを追跡できます.

  2. コレクション内の順序ではなく、表示順序で機能するクラスのGetFirstColumnGetNextColumnGetPreviousColumnGetLastColumnメソッドを使用できます。for ループを使用して、必要なコレクションが見つかるまでDataGridViewColumnCollectionコレクションを反復処理することもできます。m_DGV.Columns[i]

  3. 継承されたDataGridViewand を作成しますDataGridViewColumnCollection。新しいコレクション クラスを使用するためにDataGridView単純にオーバーライドされます。newDataGridViewColumnCollectionには、表示インデックスによってコレクションをアドレス指定するメソッドが含まれます。おそらく、必要なコレクションが見つかるまでコレクションを反復処理することによって行われます (#2 を参照)。または、ディクショナリを保存して、非常に多数の列について更新し続けることができます。

    列が移動するたびに、基本的に全体を書き直す必要があるため、辞書を保持することによるパフォーマンスの向上には疑問があります。とにかく反復処理は O(n) であり、何百もの列で非同期操作について話しているのでない限り、おそらく問題ありません。

    this[]を台無しにしないと仮定すると、演算子もオーバーライドできる場合がありますDataGridView

アイデア 1 は実装が最も簡単かもしれませんが、必ずしも最も美しいとは限りません。アイデア #2 は機能し、それを function に入れることができますDataGridViewColumn GetColumnByDisplayIndex(int Index)。アイデア #3 はかわいらしく、確かに最もカプセル化されたアプローチですが、それほど単純ではありません。

于 2008-12-10T09:00:57.023 に答える
2

これは、DataGridView の列の順序が必ずしも表示順序を決定するとは限らないためだと思われますが、デフォルトで明示的に割り当てられていない場合、列の順序は DisplayIndex プロパティの値を決定します。そのため、DisplayIndex プロパティがあるため、Insert を実行せずにコレクションに列を追加できます。DisplayIndex 値を指定するだけで、DisplayIndex が等しいかそれ以上のすべてに対してカスケード更新が行われます。あなたの例から、挿入された列は最初にスキップされた DisplayIndex 値も受け取っているようです。

私が見つけた質問/回答から:

DisplayIndex を変更すると、古い DisplayIndex と新しい DisplayIndex の間のすべての列がシフトされます。

ほとんどすべてのコレクション (LinkedList を除く) と同様に、コレクションに挿入するよりもコレクションに追加する方が常に優れています。表示されている動作は、そのルールを反映しています。

于 2008-10-22T21:55:15.810 に答える
0

優れたアドバイスをくれた cfeduke に感謝します。遅くなると思いInsertましたが、提供されたリンクは、どれだけ遅いかを教えてくれました。

これにより、DataGridView で列を動的に効率的に挿入および削除する方法の問題が生じます。Addorを使用して多数の列を追加しAddRange、実際には削除しないことが理想的な設計のようです。Visibleプロパティを falseに設定することで、削除をシミュレートできます。また、非表示の列を取得して設定し、表示することで、列を挿入できDisplayIndexます。

ただし、このアプローチでは避けるべき地雷があるのではないかと思います。何よりも、単純な方法でデータにインデックスを付けることができなくなったことです。つまり、適切にマッピングさm_DGV.Columns[i]m_DGV.Rows[n].Cells[i]ません。外部の直感的なマッピングを維持するためにマップ/辞書を作成できると思います。

私のアプリケーションは (現在設計されているように) 列の挿入と削除を頻繁に行う必要があるため、その価値があるかもしれません。誰にも提案はありますか?

于 2008-10-27T19:40:41.347 に答える