DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DataGridの特定セルの背景色変更

分類:[.NET]

お久しぶりです。また質問があります。

特定のセルだけ背景色を変更したいのですが、どぼんさんのTipsにある
DataGridColumnStyleからの派生クラスしかないのでしょうか?

    DataGrid.CurrentCell.bkColor = Color.Red
             or
    DataGrid.CurrentCell.bkColor = Brushes.Red

上記の様な感じでできると、すごく使い易いのですが。。。
なにか方法がありますでしょうか? よろしくお願いします。
■No973に返信(どらごらさんの記事)
> お久しぶりです。また質問があります。
> 
> 特定のセルだけ背景色を変更したいのですが、どぼんさんのTipsにある
> DataGridColumnStyleからの派生クラスしかないのでしょうか?
> 
>     DataGrid.CurrentCell.bkColor = Color.Red
>              or
>     DataGrid.CurrentCell.bkColor = Brushes.Red
> 
> 上記の様な感じでできると、すごく使い易いのですが。。。
> なにか方法がありますでしょうか? よろしくお願いします。
> 
> 

DataGridTextBoxColumnの派生でできますよ。
下記のクラスをカスタマイズして「GridColumnStyles」に追加してください。


   Public Class DataGridTextBoxColumnSetColor
        Inherits DataGridTextBoxColumn

        Public Sub New()
        End Sub

        '自分の大嫌いなPaintメソッド
        Protected Overloads Overrides Sub Paint(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal source As CurrencyManager, ByVal rowNum As Integer, ByVal backBrush As Brush, ByVal foreBrush As Brush, ByVal alignToRight As Boolean)
            Dim objValue As Object
            Dim intValue As Integer

            Try
                '例では、セルに0か1しか入っていないことを想定
                '変数の持ち方を変えれば応用は利きますよ!
                objValue = MyClass.GetColumnValueAtRow(source, rowNum)
                If IsNothing(objValue) = False Then
                    If IsDBNull(objValue) = False Then
                        If IsNumeric(objValue) = True Then
                            intValue = CType(objValue, Integer)
                            If intValue = 0 Then
                                '背景を赤、前景を青
                                backBrush = New SolidBrush(Color.Red)
                                foreBrush = New SolidBrush(Color.Blue)
                            ElseIf intValue = 1 Then
                                '背景を黄、前景を赤
                                backBrush = New SolidBrush(Color.Yellow)
                                foreBrush = New SolidBrush(Color.Red)
                            End If

                        End If
                    End If
                End If

            Catch ex As Exception
                'エラー時は、デフォルトの色
            Finally
                '描画
                MyBase.Paint(g, bounds, source, rowNum, backBrush, foreBrush, alignToRight)
            End Try
        End Sub
    End Class
■No975に返信(fukuさんの記事)

 レスありがとうございます。
 今日は用事があるため、月曜に検証してみます。すみません。
 ただ...

>             Try
>             Catch ex As Exception
>             Finally
>             End Try

 これができるのには、感動しました^^;
 できないと(勝手に)思い込んでいたので、ネスト階層が減りますね。
■No975に返信(fukuさんの記事)
> ■No973に返信(どらごらさんの記事)
>>特定のセルだけ背景色を変更したいのですが、どぼんさんのTipsにある
>>DataGridColumnStyleからの派生クラスしかないのでしょうか?

> DataGridTextBoxColumnの派生でできますよ。

私のTipsもDataGridTextBoxColumnからの派生クラスを作成しています。そもそもDataGridTextBoxColumnはDataGridColumnStyleからの派生クラスですよね。
日曜から、体調崩してレスできなくて申し訳ありません。

DataGridColumnStyleからの派生クラス以外と、質問したのは以下の理由からです。

1.DataGridはRow(行)毎に追加
2.DataGridColumnStyleはCol(列)毎の設定
3.そもそもDataGridのPaintとの違い?

と言うことでかなり混乱しています。
もっともCol毎に設定(マッピング)する理由は理解できるのですが、
自分が行おうとしていること(クリックされたセルの背景色を変える)を
どのようにDataGridColumnStyleに受け渡すかが、思いつきません。

P.S. 寝込んでいる時に考えた方法ですが、なんかおかしい気がして...
1.DataGrid.CurrentCellをOverrideして、bkColorプロパティを追加
2.bkColorのSetでColumn番号から、DataGridColumnStyleを特定
3.Tipsの処理
どらごらさん、横からすみません。
どぼんさんのTipsにあるやり方で行うと、

DataGrid1.TableStyles.Add(ts) を定義すると、

'TableStyles' は 'System.Web.UI.WebControls.DataGrid' のメンバではありません。

とエラーになります。
Webアプリケーションで参照設定、及びインポートの定義も良いと思うのですが。。。?
こんばんは、晋作さん。ピラルクです。

同じ"DataGrid"ですが、
System.Web.UI.WebControls と
System.Windows.Forms
のそれは全く別物です。

よって、ASP.NETで可能なことは限られます。
(オブジェクトブラウザなりで確認してみてください。TableStylesは無いですね)

別スレ(No934)の件は、環境を書いておられなかったので、
みんなSystem.Windows.Formsの話だと思っていたから、
TableStylesによるカスタマイズは使えないでしょう。
こんにちは、どらごらさん。ピラルクです。

> 自分が行おうとしていること(クリックされたセルの背景色を変える)を
> どのようにDataGridColumnStyleに受け渡すかが、思いつきません。

受け渡してやる必要はありません。
それは親元であるDataGridがやってくれます。

スクロールされるなりの何らかの理由でDataGridのPaintが呼ばれる

DataGridのPaintでは、各列毎のDataGridColumnStyleに列の描画を依頼する

見えている行の範囲に対して、DataGridColumnStyleのPaintが呼ばれる

DataGridColumnStyleのPaintは、rowNumでどの行の描画を依頼されている
のかを判定し(Cellを一意に特定できる)、そのセルにあった描画を行う。

DataGridColumnStyleのインスタンスは自分がどの列を担当してい
るかは知っているはずで、rowNum という値でセルの座標がわかる。
あとはPaintでその1セルを描画するだけの処理を記述すればいい。
見えている行数分、DataGridがPaintを何発も呼び出してくれる。

クリックされたセルかどうかを見分けるには、
Me.DataGridTableStyle.DataGrid.CurrentRowIndex (←他にありそう)
と比較するか、EditでControlを表示させているならそこで対処するか
になるのだと思います。

(...おそらく(^^; すいません.私も勉強中)

> P.S. 寝込んでいる時に考えた方法ですが、なんかおかしい気がして...
> 1.DataGrid.CurrentCellをOverrideして、bkColorプロパティを追加

CurrentCellは座標位置的な情報だから無理では。
(しかし、寝込んでいる間にこんな連想ができるとは凄い!)

> 2.bkColorのSetでColumn番号から、DataGridColumnStyleを特定

(?_?)

> 3.Tipsの処理

なにか課題多そうですね。(^^;
> 別スレ(No934)の件は、環境を書いておられなかったので、
> みんなSystem.Windows.Formsの話だと思っていたから、
> TableStylesによるカスタマイズは使えないでしょう。

 System.Web.UI.WebControlsにもそういえばありましたね。
 僕のほうも、System.Windows.Formsだと書いとけばよかったです。
 すみませんでした>ALL&晋作さん

 一応Tipsのやり方は、動作しています。
どらごらです。

難しく考えないで、MyDataGridTextBoxColumnにイベントを1つ追加しました。
そしたら、まぁ〜100%期待通りと言うわけでは、無いですがうまくいきました。
#PaintイベントをPublicにすればいい?

追加したCellPaintイベントで、好きなように(アプリ側で)処理できるので
一応満足しました。ただ他にもありそうな気がするんですけどね^^;

皆さん、ありがとうございました。

----
Public Class Form3
    Inherits System.Windows.Forms.Form

#Region " Windows フォーム デザイナで生成されたコード "
'Form3にDataGrid1を置いただけです。
...
#End Region

    Private Sub Form3_Load(ByVal sender As System.Object, _
            ByVal e As System.EventArgs _
            ) Handles MyBase.Load

        Dim tmpTable As System.Data.DataTable = New DataTable("DataTable1")
        Dim tmpRow As System.Data.DataRow
        Dim ts As New DataGridTableStyle
        Dim cs As MyDataGridTextBoxColumn

        '初期化
        Randomize()
        tmpTable.Columns.Add("Column1")
        tmpTable.Columns.Add("Column2")

        'データ追加(当方2003のため)
        For I As Integer = 0 To 5
            tmpRow = tmpTable.NewRow()
            tmpRow(0) = CStr(Int(2 * Rnd()))    '0-1 as String)
            tmpRow(1) = CStr(Int(2 * Rnd()))    '0-1 as String
            tmpTable.Rows.Add(tmpRow)
        Next
        DataGrid1.DataSource = tmpTable

        'Tipsそのまんま
        ts.MappingName = "DataTable1"
        cs = New MyDataGridTextBoxColumn
        cs.MappingName = "Column1"
        AddHandler cs.CellPaint, AddressOf gcsPaint        '追加
        ts.GridColumnStyles.Add(cs)
        cs = New MyDataGridTextBoxColumn
        cs.MappingName = "Column2"
        AddHandler cs.CellPaint, AddressOf gcsPaint        '追加
        ts.GridColumnStyles.Add(cs)
        DataGrid1.TableStyles.Add(ts)

    End Sub

    Private Sub gcsPaint( _
            ByVal ColumnMappingName As String, _
            ByVal rowNum As Integer, _
            ByRef backBrush As Brush, _
            ByRef foreBrush As Brush _
            )
        backBrush = Brushes.White

        Select Case ColumnMappingName
            Case "Column1"
                If rowNum Mod 2 = 0 Then
                    backBrush = Brushes.Red
                End If
            Case "Column2"
                If rowNum Mod 2 = 0 Then
                    backBrush = Brushes.Yellow
                End If
        End Select
    End Sub
End Class

Public Class MyDataGridTextBoxColumn
    Inherits DataGridTextBoxColumn

    Public Event CellPaint( _
            ByVal ColumnMappingName As String, _
            ByVal rowNum As Integer, _
            ByRef backBrush As Brush, _
            ByRef foreBrush As Brush _
            )

    Protected Overloads Overrides Sub Paint( _
            ByVal g As Graphics, _
            ByVal bounds As Rectangle, _
            ByVal source As CurrencyManager, _
            ByVal rowNum As Integer, _
            ByVal backBrush As Brush, _
            ByVal foreBrush As Brush, _
            ByVal alignToRight As Boolean _
            )

        RaiseEvent CellPaint(Me.MappingName, rowNum, backBrush, foreBrush)

        MyBase.Paint(g, bounds, source, rowNum, _
            backBrush, foreBrush, alignToRight)
    End Sub
End Class
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板