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

DataGridのPaintイベント

環境/言語:[WindowsXP、Microsoft .NET Framework 1.1]
分類:[.NET]

現在、
◆DataGrid内の特定のセルの色を変える
http://dobon.net/vb/dotnet/datagrid/coloredcell.html
を参考に、Paintメソッドをオーバーライドし
特定のセルに対して編集を行っています。

その際に、
「ListManagerへの位置はrowNumと同じでなければなりません」
というエラーが発生してしまい、それはセルを更新するタイミングで
CurrencyManagerが指す行と、DataGridが指す行が一致しないように
なってしまっていた為のようでしたので、
source.Position = rowNum
という形で、CurrencyManagerのPositionに編集中の行番号を
渡す処理を追加したところ、そのエラーは消えました。

しかし、その後オーバーライドしたPaintメソッドが無限ループ
(ずっとイベントが発生して呼び出され続けている)
という現象が起きてしまい、解決方法が見付かりません。

拙い質問で申し訳ありませんが、どなたがお分かりになる方が
いらっしゃいましたら、ご教授ください。
お世話になります。

追加ですが、オーバーライドしたPrintメソッド内では、
MyBaseのPaintをCallしています。

どなたかお分かりになりましたら、お願い致します。
> どなたかお分かりになりましたら、お願い致します。

ちょっとこれだけの質問の内容からですとわかりかねます。できれば、Paint部分のコードを見せてもらえませんか?
■No17568に返信(trapemiyaさんの記事)
>>どなたかお分かりになりましたら、お願い致します。
>
> ちょっとこれだけの質問の内容からですとわかりかねます。できれば、Paint部分のコードを見せてもらえませんか?

お返事ありがとうございます。
下記がPaint部分のコードになります。

'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 strMsg As String
Dim dvMsg As New DataView
dvMsg = tblMsg.DefaultView

'セルの値を取得する
Dim cellValue As Object = Me.GetColumnValueAtRow(source, rowNum)

'前景色と背景色を変える
If Not cellValue Is Nothing And _
Not cellValue Is DBNull.Value Then
Dim strTextSplit() As String = CType(cellValue, String).Split(",")
Select Case strTextSplit(0)
Case "S01"
dvMsg.RowFilter = "MsgCode = 'S01'"
strMsg = dvMsg(0)("Msg")
SetColumnValueAtRow(source, rowNum, strMsg)
CellForeColor = Color.Blue
Case "S02"
dvMsg.RowFilter = "MsgCode = 'S02'"
strMsg = dvMsg(0)("Msg")
SetColumnValueAtRow(source, rowNum, strMsg)
CellForeColor = Color.Red
Case "S03"
dvMsg.RowFilter = "MsgCode = 'S03'"
strMsg = dvMsg(0)("Msg")
SetColumnValueAtRow(source, rowNum, strMsg)
CellForeColor = Color.YellowGreen
Case "S04"
dvMsg.RowFilter = "MsgCode = 'S04'"
strMsg = dvMsg(0)("Msg")
SetColumnValueAtRow(source, rowNum, strMsg)
CellForeColor = Color.YellowGreen
Case "S05"
dvMsg.RowFilter = "MsgCode = 'S05'"
strMsg = dvMsg(0)("Msg")
SetColumnValueAtRow(source, rowNum, strMsg)
CellForeColor = Color.Black
Case Else

End Select
End If

foreBrush = New SolidBrush(_CellForeColor)

source.Position = rowNum

'基本クラスのPaintメソッドを呼び出す
MyBase.Paint(g, bounds, source, rowNum, backBrush, foreBrush, alignToRight)

End Sub

問題点ですが、
・SetColumnValueAtRow(source, rowNum, strMsg)
のカラム値の変更タイミングで、CurrencyManager(source)とrowNumの
さしている位置がズレてしまう事。(他クラスのメンバの為でしょうか?)
・source.Positon = rowNum
CurrencyManager(source)とrowNumのさしている位置を合わせる為に
入れましたが、その部分がある為に再度Gridを書き直そうとして
無限ループ?のような状態になってしまっている事。

上記の問題を解決したいです。
よろしくお願い致します。
おそらくSetColumnValueAtRowが問題のような気がします。Paint内でセルの値を変えるわけですから、またPaintが呼ばれるという循環に陥っているのではないでしょうか?
SetColumnValueAtRowを使うのではなく、DrawStringで直接文字を描いてください。
■No17577に返信(trapemiyaさんの記事)
> おそらくSetColumnValueAtRowが問題のような気がします。Paint内でセルの値を変えるわけですから、またPaintが呼ばれるという循環に陥っているのではないでしょうか?
> SetColumnValueAtRowを使うのではなく、DrawStringで直接文字を描いてください。

trapemiya 様

ご返答ありがとうございます。
DrawStringというメソッドがあるのを初めて知りました。
dvMsg.RowFilter = "MsgCode = 'S01'"
strMsg = dvMsg(0)("Msg")
Dim sf As New StringFormat

'配置を指定する
Select Case Me.Alignment
Case HorizontalAlignment.Left
sf.Alignment = StringAlignment.Near
Case HorizontalAlignment.Center
sf.Alignment = StringAlignment.Center
Case HorizontalAlignment.Right
sf.Alignment = StringAlignment.Far
End Select

'テキストの方向を指定する
If alignToRight Then
sf.FormatFlags = sf.FormatFlags Or StringFormatFlags.DirectionRightToLeft
End If

Dim rectf As New RectangleF(bounds.X, bounds.Y, bounds.Width, bounds.Height)
rectf.Inflate(-_margin.X, -_margin.Y)

g.DrawString(strMsg, DataGridTableStyle.DataGrid.Font, foreBrush, rectf, sf)
CellForeColor = Color.Blue

文字色は青色で表示されますが、書きたい文字列は変える事が
出来ませんでした。
(ちなみに、↓を参考にしました。)
 http://dobon.net/vb/dotnet/datagrid/datagridlinklabel.html
もう少し色々挑戦してみます。

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