DataGridViewを強制的にすべてのセルに対してそのセルフォーマットイベントを発射する方法はありますか?
-
11-12-2019 - |
質問
私達は私達のアプリケーション全体にわたって様々なグリッドのカラーコードセルにセルフォーマットイベントを使用します。
Excelへのエクスポートを処理する一般的なコードを持っています(そして印刷)が白黒でそれを行いました。これを変更してグリッドから色を拾いたい。
この質問&答えは(そしてそれが機能します)...拡張されたより大きなグリッドの問題があることを除いて...単一の画面を超えて。画面にまだ表示されていないグリッドの部分は(論理的に)セルフォーマットコードを発射させることはありませんので、その基礎となる色は設定されません。その結果、Excelでは、カラーコーディングはの半分の途中でFizzles。
3つの解決策があるようです:
1)Excelへのエクスポートを行う前に、彼がグリッドのすべての部分までスクロールする必要があると伝えます。 ha!深刻な解決策ではない
2)Excelへのエクスポートを実行する前に、グリッドのすべての部分までプログラム的にスクロールします。 (1) より低く恐ろしいのみ恐ろしい
3)Excelコードへのエクスポートで、上部に何かを発射して、地域全体をペイント/フォーマットするようにDataGridViewに告げる。
.
MyDataGridView.FormatAllCells()
このようなものをするものはありますか???
ああ、4番目のオプションがありますが、これは既存の既存のコードに触れることを含みます:
4)セルフォーマットイベントの使用を停止し、ロード時間でセルをフォーマットします。これに問題があるのは、CellFormattingが1年のドット以来それを行った方法であるため、アプリケーションですべてのグリッドを再利用する必要があります。
解決 3
@Davidhallが提案すると、Magic .FormatAllCells
はないと仮定しています。
グリッドのDataBindingComplete
イベントを使用していることを示唆する投稿を最終的に見つけました。そしてこれは作品です。
確かに、この解決策は私の不要なオプション「4」の変種です。
他のヒント
私は可能な解決策を持っています - あなたのエクスポート関数には、各セルのCell.FormattedValueプロパティにアクセスします。 microsoft によると、これは強制的に火災へのセルフォーマットイベント。
他の回答で述べたように、DataGridViewCell.FormattedValue
にアクセスすることは、特定のセルに対してCellFormatting
イベントを(再)呼び出されるように強制するための簡単な方法です。ただし、私の場合、このプロパティはまた、カラムの自動サイズ変更を含む望ましくない副作用をもたらしました。作業可能な解決策に長時間検索しながら、私はついに完全に機能する次のマジックメソッドに遭遇しました。
これらの4つの方法は、指定されたスコープ(セル、列、行、または表の全体の表だけ)に対してのみ呼び出されるように、そしてまた厄介な自動サイズ変更アーチファクトを引き起こすことなく、強制的に呼びかけます。
私は同じ問題を抱えていて、私はあなたの解決策#4と非常に似たものに終わりました。
あなたのように、DataBindingComplete
イベントを使用しました。しかし、私は拡張方法を使用していたので、既存のコードの変更は準備ができています:
internal static class DataGridViewExtention
{
public static void SetGridBackColorMyStyle(this DataGridView p_dgvToManipulate)
{
p_dgvToManipulate.RowPrePaint += p_dgvToManipulate_RowPrePaint;
p_dgvToManipulate.DataBindingComplete += p_dgvToManipulate_DataBindingComplete;
}
// for the first part - Coloring the whole grid I used the `DataGridView.DataBindingComplete` event:
private static void p_dgvToManipulate_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
foreach (DataGridViewRow objCurrRow in ((DataGridView)sender).Rows)
{
// Get the domain object from row
DomainObject objSelectedItem = (DomainObject)objCurrRow.DataBoundItem;
// if item is valid ....
if objSelectedItem != null)
{
// Change backcolor of row using my method
objCurrRow.DefaultCellStyle.BackColor = GetColorForMyRow(objSelectedItem);
}
}
}
// for the second part (disabling the Selected row from effecting the BackColor i've setted myself, i've used `DataGridView.RowPrePaint` event:
private static void p_dgvToManipulate_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
// If current row about to be painted is selected by user
if (((DataGridView)sender).Rows[e.RowIndex].Selected)
{
// Get current grid row
var objGridRow = ((DataGridView)sender).Rows[e.RowIndex];
// Get selectedItem
DomainObject objSelectedItem = (DomainObject)objGridRow.DataBoundItem;
// if item is valid ....
if (objSelectedItem != null && objSelectedItem.ObjectId != 0)
{
// Set color for row instead of "DefaultCellStyle" (same color as we used at DataBindingComplete event)
objGridRow.DefaultCellStyle.SelectionBackColor = GetColorForMyRow(objSelectedItem);
}
// Since the selected row is no longer unique, we need to let the used to identify it by making the font Bold
objGridRow.DefaultCellStyle.Font = new Font(((DataGridView)sender).Font.FontFamily, ((DataGridView)sender).Font.Size, FontStyle.Bold);
}
// If current row is not selected by user
else
{
// Make sure the Font is not Bold. (for not misleading the user about selected row...)
((DataGridView)sender).Rows[e.RowIndex].DefaultCellStyle.Font = new Font(((DataGridView)sender).Font.FontFamily,
((DataGridView)sender).Font.Size, FontStyle.Regular);
}
}
}
. セルフォーマットイベントの間に提供されているフォーマットを再利用したい場合(例えば、FontBoldとBackgroundColorのようなCellStyle-Elements)。これらのセルスタイルは、「Cellformatting」と「CellPainting」イベントの間でのみ利用可能であるように見えますが、DataGridView - Cellのスタイル自体ではありません。
セルファルイベントの間にセルスタイルをキャプチャします。
-
ExportModuleでは、CellStylesを保存するために共有リスト、配列または辞書を追加します。
Dim oDataGridFormattingDictionary as Dictionary(Of String, DataGridViewCellStyle) = nothing
-
辞書を初期化し、印刷コードまたはエクスポートコードのDataGridViewに2番目のハンドラを追加します。 vb.netでは、このようなもの:
oDataGridFormattingDictionary = New Dictionary(Of String, DataGridViewCellStyle) AddHandler MyDatagridviewControl.CellFormatting, AddressOf OnPrintDataGridView_CellFormatting
-
ハンドラのコードを追加する
Private Sub OnPrintDataGridView_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) If e.RowIndex > -1 AndAlso e.ColumnIndex > -1 AndAlso Not e.CellStyle Is Nothing Then If Not oDataGridFormattingDictionary Is Nothing andalso oDataGridFormattingDictionary.ContainsKey(e.RowIndex & "_" & e.ColumnIndex) = False Then oDataGridFormattingDictionary.Add(e.RowIndex & "_" & e.ColumnIndex, e.CellStyle) End If End If End Sub
-
非常に重要な:実際には、実際にあなたが実際にあなたが呼び出されなければならないことを確認するために、 formattedvalue を要求する必要があることを確認するために印刷したい各セルについて(例:
.oValue = Datagridview.rows(printRowIndex).Cells(printColumnIndex).FormattedValue)
!
-
印刷するときは、セルにフォーマットがあるかどうかを確認できるようになりました。 e.g。:
if not oDataGridFormattingDictionary is nothing andalso oDataGridFormattingDictionary.ContainsKey(printRowIndex & "_" & printColumnIndex) Then ... the cellstyle is accesible via: oDataGridFormattingDictionary(printRowIndex & "_" & printColumnIndex) end if
-
エクスポートまたはPrintCodeの終わりにハンドラを削除し、辞書を何もしないように設定します
RemoveHandler DirectCast(itemToPrint.TheControl, DataGridView).CellFormatting, AddressOf OnPrintDataGridView_CellFormatting oDataGridFormattingDictionary = nothing