15

CellFormattingイベントを使用して、アプリケーション全体のさまざまなグリッドのセルを色分けします。

Excelへのエクスポート(および印刷)を処理する一般的なコードがいくつかありますが、それは白黒で行われます。これを変更して、グリッドから色を取得します。

この質問と回答は役に立ちました(そしてそれは機能します)...単一の画面を超えて広がるより大きなグリッドに問題があることを除いて。画面にまだ表示されていないグリッドの部分は、(論理的に)CellFormattingコードが実行されることはないため、基になる色が設定されることはありません。その結果、Excelでは、色分けがページの途中で消えてしまいます。

3つの解決策があるようです:

1)Excelにエクスポートする前に、グリッドのすべての部分にスクロールする必要があることをユーザーに伝えます。ハ!深刻な解決策ではありません

2)Excelにエクスポートする前に、プログラムでグリッドのすべての部分にスクロールします。(1)よりもわずかに恐ろしいだけです

3)Excelコードへのエクスポートで、上部に何かを起動して、DataGridViewにその領域全体をペイント/フォーマットするように指示します。

  MyDataGridView.FormatAllCells()

このようなことをする何かがありますか?

ああ、4番目のオプションがありますが、これには大量の既存のコードに触れることが含まれます。

4)CellFormattingイベントの使用を停止し、ロード時にセルをフォーマットします。これに関する問題は、CellFormattingがyear dot以来行ってきた方法であるため、アプリケーション内のすべてのグリッドを再ツール化する必要があることです。

4

5 に答える 5

6

考えられる解決策があります-エクスポート関数で、各セルのCell.FormattedValueプロパティにアクセスします。Microsoftによると、これによりCellFormattingイベントが強制的に発生します。

于 2012-05-27T19:24:49.767 に答える
6

他の回答で述べたように、にアクセスすることは、特定のセルに対してイベントを(再)呼び出すDataGridViewCell.FormattedValueように強制する簡単な方法です。CellFormattingただし、私の場合、このプロパティは、列の自動サイズ変更に関連する望ましくない副作用も引き起こしていました。実行可能な解決策を長い間探していたとき、私はついに完全に機能する次の魔法の方法に出会いましたDataGridView.Invalidate()、、、、DataGridView.InvalidateColumn()DataGridView.InvalidateRow()DataGridView.InvalidateCell()

これらの4つのメソッドCellFormattingは、指定されたスコープ(セル、列、行、またはテーブル全体)に対してのみ、また厄介な自動サイズ変更アーティファクトを発生させることなく、イベントを強制的に再呼び出しします。

于 2017-05-04T08:54:00.543 に答える
2

私は同じ問題を抱えていて、あなたの解決策#4に非常によく似たものになってしまいました。あなたのように、私はDataBindingCompleteイベントを使用しました。しかし、Extensionメソッドを使用したので、既存のコードの変更は耐えられます。

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);
        }
    }
}
于 2012-10-31T22:21:38.603 に答える
2

@DavidHallが示唆しているように、.FormatAllCells私たちの唯一の選択肢はCellFormattingの使用をやめることです。

ただし、ここでの新しい問題は、読み込み中にセルスタイルの書式を適用しても効果がないように見えることです。あなたがそれをグーグルするならば、そこにたくさんの投稿があります。また、フォームのボタンの下に同じコードを配置し、ロード後にクリックすると、コードが機能することも指摘されています(したがって、スタイリングを適用する前にグリッドを表示する必要があります)。このトピックに関するほとんどのアドバイスは、...ドラムロール...CellFormattingを使用することを提案しています。ああ!

最終的DataBindingCompleteに、グリッドのイベントの使用を提案する投稿が見つかりました。そして、これは機能します。

確かに、このソリューションは私の不要なオプション「4」の変形です。

于 2012-05-18T14:37:56.193 に答える
1

Cellformatting-event中に提供されたフォーマット(たとえば、fontboldやbackgroundcolorなどのcellstyle-elements)を再利用したい場合に考えられる解決策。これらのセルスタイルは、「cellformatting」イベントと「cellpainting」イベントの間でのみ使用可能であり、datagridview-cellのスタイル自体では使用できないようです。

次のような2番目のハンドラーを使用して、cellformatting-event中にセルスタイルをキャプチャします。

  1. exportmoduleで、共有リスト、配列、または辞書を追加して、セルスタイルを保存します。

    Dim oDataGridFormattingDictionary as  Dictionary(Of String, DataGridViewCellStyle) = nothing
    
  2. 辞書を初期化し、印刷またはエクスポートコードのdatagridviewに2番目のハンドラーを追加します。vb.netでは次のようなものです:

     oDataGridFormattingDictionary = New Dictionary(Of String, DataGridViewCellStyle)
     AddHandler MyDatagridviewControl.CellFormatting, AddressOf OnPrintDataGridView_CellFormatting
    
  3. ハンドラーのコードを追加します

    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
    
  4. 非常に重要:元のcellformatting-event(およびその後の2番目のcellformatting-handler)が実際に呼び出されるようにするには、印刷する各セルのformattedvalueを要求する必要があります(例:

    oValue = Datagridview.rows(printRowIndex).Cells(printColumnIndex).FormattedValue)
    

  5. 印刷時に、セルに書式が設定されているかどうかを確認できるようになりました。例えば:

    if not oDataGridFormattingDictionary is nothing andalso oDataGridFormattingDictionary.ContainsKey(printRowIndex & "_" & printColumnIndex) Then
    ... the cellstyle is accesible via:
    oDataGridFormattingDictionary(printRowIndex & "_" & printColumnIndex)
    end if 
    
  6. エクスポートまたは印刷コードの最後にハンドラーを削除し、辞書を何も設定しない

    RemoveHandler DirectCast(itemToPrint.TheControl, DataGridView).CellFormatting, AddressOf OnPrintDataGridView_CellFormatting
    oDataGridFormattingDictionary = nothing
    
于 2015-06-23T11:41:57.673 に答える