- PR -

DataGridViewTextBoxColumnに追加したプロパティの値が保存されない

投稿者投稿内容
kai
会議室デビュー日: 2006/10/10
投稿数: 5
投稿日時: 2006-10-10 16:48
kaiと申します。環境は.NET2005でVB.NETを使用して作成しています。

DataGridViewTextBoxColumnにプロパティを追加して追加された列にカーソルがある場合に背景色が変更されるカスタムコントロールを作成したいと考えています。そこで以下のような記述を行い動作は確認することができました。しかしデザインに設定したGotFocusColorプロパティの値が列の編集ウィンドウを閉じると元の値に戻ってしまうという現象に悩まされています。同じような目的でTextBoxから作成したコントロールは問題なく動いているのですが何か考え方に間違いがあるのでしょうか?

Public Class MyTextBoxColumn
Inherits System.Windows.Forms.DataGridViewTextBoxColumn

Private _GotFocusBackColor As Color 'フォーカス取得時の背景色
Private _LostFocusBackColor As Color 'フォーカス喪失時の背景色

Public Property GotFocusBackColor() As Color
Get
Return _GotFocusBackColor
End Get
Set(ByVal value As Color)
_GotFocusBackColor = value
End Set
End Property

Public Sub New()
InitializeComponent() '呼び出しの後で初期化を追加します。
_GotFocusBackColor = Color.LightYellow '初期値:薄い黄色

Dim cell As New MyTextBoxCell
Me.CellTemplate = cell
End Sub
End Class

Public Class MyTextBoxCell
Inherits System.Windows.Forms.DataGridViewTextBoxCell

Private _GotFocusBackColor As Color 'フォーカス取得時の背景色
Private _LostFocusBackColor As Color 'フォーカス喪失時の背景色

Public Sub New()

End Sub

Protected Overrides Sub OnEnter(ByVal rowIndex As Integer, ByVal throughMouseClick As Boolean)
Dim col As MyTextBoxColumn
col = Me.OwningColumn

'TextBoxColumnの情報を参照する
If Not col Is Nothing Then
_LostFocusBackColor = col.InheritedStyle.BackColor
_GotFocusBackColor = col.GotFocusBackColor
End If

Style.BackColor = _GotFocusBackColor
End Sub

Protected Overrides Sub OnLeave(ByVal rowIndex As Integer, ByVal throughMouseClick As Boolean)
Style.BackColor = _LostFocusBackColor
End Sub
End Class
masa
大ベテラン
会議室デビュー日: 2004/10/28
投稿数: 161
投稿日時: 2006-10-10 17:31
> 列の編集ウィンドウを閉じると元の値に戻ってしまう

OnEnter でのスタイル変更はうまくいっているのですね?
知らない間に OnLeave が発生していることはありませんか?

"編集ウィンドウ" とは入力ダイアログのようなものでしょうか。
ダイアログを開くときに OnLeave は発生していませんか?
kai
会議室デビュー日: 2006/10/10
投稿数: 5
投稿日時: 2006-10-10 18:02
返信ありがとうございます。

>>OnEnter でのスタイル変更はうまくいっているのですね?
こちらは希望の動作を確認できています。

>>"編集ウィンドウ" とは入力ダイアログのようなものでしょうか。
デザイン時にDataGridViewを右クリックすると表示される「列の編集」から表示されるウィンドウを意味していました。こちらに追加されたGotFocusBackColorというプロパティが表示されているのですが、色を変更してウィンドウを閉じた後に再度開くと元の色に戻っているという状況です。


OnLeaveについては調査してみます。
masa
大ベテラン
会議室デビュー日: 2004/10/28
投稿数: 161
投稿日時: 2006-10-10 18:29
DataGridView がどのようにイベントを実装しているかによりますが、
おそらくはデザイン時と実行時と同じコードによってイベントが発生していると思います。

OnEnter が発生しているのであればスタイルが初期化(?)されてしまう原因としては、

・OnLeave が発生している

 (グリッド自身の OnLeave → セルの OnLeave のように)

・セルインスタンスが再生成されている

 デザイン時はデザイナによっていろいろ再生成されているかもしれません。
 デザイン時に、表示されているそれぞれのセルの内容が
 そのまま InisializeCompornent に出力されているわけではないでしょうから。
 実行時には問題がなく、デザイン時のみということであれば可能性大ではないでしょうか。
Ahf
大ベテラン
会議室デビュー日: 2006/08/16
投稿数: 172
投稿日時: 2006-10-10 18:58
MyTextBoxCellクラスでCloneメソッドを実装する必要がある気がします。
コード:
Public Overrides Function Clone() As Object
  'プロパティのクローン作成
  Dim cloneCell As New MyTextBoxCell

  '色の設定をコピー

  Return cloneCell
End Function



もうひとつ自分の実装と比べて思ったのですが、
MyTextBoxColumnクラスでCellTemplateプロパティもオーバーライドするんじゃなかったかなぁ・・・と。
kai
会議室デビュー日: 2006/10/10
投稿数: 5
投稿日時: 2006-10-11 08:41
返信ありがとうございます。

>>・OnLeave が発生している
確認してみましたがOnLeaveは発生していませんでした。

>>・セルインスタンスが再生成されている
>>デザイン時はデザイナによっていろいろ再生成されているかもしれません。
実行時にコードから背景色の変更を指定すると希望の動作となりました。デザイン時に再構成されているとしても他のプロパティは変更が維持されているのですが、これらはどう保存されているのでしょうか。

>>MyTextBoxCellクラスでCloneメソッドを実装する必要がある気がします。
こちらはMyTextBoxColumnですよね?実装してみましたが状況は変わりませんでした。

>>MyTextBoxColumnクラスでCellTemplateプロパティもオーバーライドするんじゃなかったかなぁ・・・と。
こちらも実装してみましたが変化ないようです。但し、オーバーライドしただけで何をするべきなのかよくわからず単にオーバーライドしただけでしたので誤っているかもしれません。

調査したことや、お教えいただいた点を反映したソースはこのようになっております。
--------------------------------------
Imports System.ComponentModel

Public Class MyTextBoxColumn
  Inherits System.Windows.Forms.DataGridViewTextBoxColumn

  Private _GotFocusBackColor As Color = Color.LightYellow     'フォーカス取得時の背景色
  Private _LostFocusBackColor As Color    'フォーカス喪失時の背景色

  <Category("表示")> _
  <Description("フォーカス取得時の背景色を設定します。")> _
  Public Property GotFocusBackColor() As Color
    Get
      Return _GotFocusBackColor
    End Get
    Set(ByVal value As Color)
      _GotFocusBackColor = value
    End Set
  End Property

  Private Function ShouldSerializeGotFocusBackColor() As Boolean
    Return Not GotFocusBackColor.Equals(Color.LightYellow)
  End Function

  Public Sub New()
    InitializeComponent() '呼び出しの後で初期化を追加します。

    Dim cell As New MyTextBoxCell
    Me.CellTemplate = cell
  End Sub

  Public Overridable Shadows Function Clone() As Object
    Dim cloneObj As New MyTextBoxColumn
    cloneObj.GotFocusBackColor = Me.GotFocusBackColor
    Return cloneObj
  End Function
End Class

Public Class MyTextBoxCell
  Inherits System.Windows.Forms.DataGridViewTextBoxCell

  Private _GotFocusBackColor As Color     'フォーカス取得時の背景色
  Private _LostFocusBackColor As Color    'フォーカス喪失時の背景色

  Public Sub New()
    Try
    Catch
    End Try
  End Sub

  Protected Overrides Sub OnEnter(ByVal rowIndex As Integer, ByVal throughMouseClick As Boolean)
    Dim col As MyTextBoxColumn
    col = Me.OwningColumn

    'TextBoxColumnの情報を参照する
    If Not col Is Nothing Then
      _LostFocusBackColor = col.InheritedStyle.BackColor
      _GotFocusBackColor = col.GotFocusBackColor
    End If

    Style.BackColor = _GotFocusBackColor
  End Sub

  Protected Overrides Sub OnLeave(ByVal rowIndex As Integer, ByVal throughMouseClick As Boolean)
    Style.BackColor = _LostFocusBackColor
  End Sub
End Class

masa
大ベテラン
会議室デビュー日: 2004/10/28
投稿数: 161
投稿日時: 2006-10-11 09:06
デザイン時のみの問題ということですね。

編集ウィンドウはセルのプロパティ編集だと思います。
全くの推測になりますが、これを閉じたときは、
プロパティを変更するのではなく、
そのセルを再生成しているのではないでしょうか。

セルや行のインスタンスはいろいろな場面で再生成されていたりします。
特に仮想モードでは顕著ですね。

他のプロパティは反映されているとのことですが、
InitializeCompornent の中には値を設定するコードなり、
コンストラクタなりありませんか?
今回のスタイルはイベントによって動的に設定されるものであるため、
セルのインスタンス生成時には未設定の状態となっていると思います。

実行時に問題とならなければそれでよし、という考え方もあるような気もします。


追記

セルというより、セルの書式に関連するプロパティを編集すると、
全てまとめてスタイルが再生成されているのかも。


[ メッセージ編集済み 編集者: masa 編集日時 2006-10-11 09:59 ]
Ahf
大ベテラン
会議室デビュー日: 2006/08/16
投稿数: 172
投稿日時: 2006-10-11 09:27
私が以前に新しくプロパティを拡張するようにカスタマイズした際、
次のようなロジックを組み込んでいました。

・MyTextBoxColumnではオーバーライドしたCellTemplateプロパティを通して
 セルのプロパティへアクセスする。〜Columnクラスのコンストラクタで
コード:
MyBase.New(New MyTextBoxCell)


 とし、拡張したプロパティでは
コード:
DirectCast(MyBase.CellTemplate, MyTextBoxCell).[なにか]= value


 としていた。
・MyTextBoxCellではCloneメソッドをオーバーライドし拡張したプロパティを
 付与した形で自分自身のクローンを返却するようにする

というように、MyTextBoxCellクラスにCloneメソッドを、MyTextBoxColumnクラスに
CellTemplateプロパティのオーバーライドをやっていました。デザイン時には、
〜Columnクラスのプロパティは内部的に〜Cellクラスのプロパティをアクセスする
ような感じですね・・・。

つたない文章で申し訳ないです。

スキルアップ/キャリアアップ(JOB@IT)