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

Form内のDatagridview書式指定を.Showメソッド実行前に行った場合の描画の立ち遅れを解消したい

環境/言語:[Windows7, .NET Framewor3.5 ]
分類:[.NET]

いつもお世話になっております。

あるFormを.Showdialogする前に、そのForm上のDatagridviewの更新を行った場合、その
Datagridviewの描画(BackColorやFontStyle.Bold)が追いつかないようで、解決法を
探しています。

厳密に言うと、Form1からForm2のインスタンスを作り、Showする前に、Form2上の
Datagridviewの更新/書式指定処理を呼び出し、その後、Form2を.Showdialogした場合、
Form2上のDataGridviewの書式の描画は指定した通り行われません。

下記がコードです。
ちなみに、コメントアウトしている箇所をコメントインすると、
一旦Showして、DGVを更新して、またhideして、Showdialogするので、ひとまずは
描画遅れの現象を回避することに成功するようです。ただし、このような姑息な
方法でなく、もっとスマートなコーディングは無いものかと思い質問させて頂いた次第
です。

また、なぜDatagridviewの描画においてこのようなことが発生するかという原因も気に
なっております。


Public Class Form1

    'Button : Button1をデザイナ上で載せたフォーム。

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim F2 As New Form2

        'F2.Show()
        F2.REFRESH_DGV()
        'F2.Hide()

        F2.ShowDialog()

    End Sub
End Class

Public Class Form2

    'Datagridview : DGV をデザイナ上で載せたフォーム。

    Public Sub REFRESH_DGV()

        Dim DT As New DataTable

        DT.Columns.Add("aa")
        DT.Columns.Add("bb")

        DT.Rows.Add(New Object() {100, 200})
        DT.Rows.Add(New Object() {300, 400})

        DGV.AutoGenerateColumns = True
        DGV.DataSource = DT

        DGV.Rows(0).DefaultCellStyle.BackColor = Color.LightBlue
        DGV.Rows(1).DefaultCellStyle.Font = New Font(DGV.Font, FontStyle.Bold)


    End Sub

End Class


(上記コードForm1の最後での.Showdialogはマストです。.Showだけだったら.Showしてから
更新処理を呼び出せばいい話なので、その場合は問題にならないので。
また、Form2のLoadイベントに処理を記述するというのも、わけあって使いたくない
手段です。)

宜しくお願いいたします。
2013/12/09(Mon) 09:12:49 編集(投稿者)

■No31985に返信(kane123さんの記事)
> F2.ShowDialog()
ShowDialog を使う際には、Using ブロックを併用しましょう。
http://msdn.microsoft.com/ja-jp/library/c7ykbedk%28vs.110%29.aspx

》 ダイアログ ボックスとして表示されているフォームは閉じられるのではなく
》 非表示になるため、フォームがアプリケーションで不要になった場合は、
》 そのフォームの Dispose メソッドを呼び出す必要があります。



> また、Form2のLoadイベントに処理を記述するというのも、わけあって使いたくない
> 手段です。)
Load イベントを使いたくない理由を明かしてもらわないと、
解決策を提示しにくいです…。Shown イベントも駄目なのでしょうか?

Using F2 As New Form2()
  'AddHandler F2.Load, AddressOf F2.REFRESH_DGV
  AddHandler F2.Shown, AddressOf F2.REFRESH_DGV
  F2.ShowDialog()
End Using


> なぜDatagridviewの描画においてこのようなことが発生するか
コントロールがロードされる前、より正確に言えば、DataGridView の
IsHandleCreated プロパティが False のときにセットするとそうなるようですね。
親元の DGV.DefaultCellStyle は反映されるようですけれども。

これは Form に限った話ではなく、TabControl の 2ページ目以降に配置した
DataGridView でも発生する現象だったりします。そのタブページが実際に
表示される前に操作した場合、一部のプロパティが初期値に戻ってしまうという。
(TabControl の場合は、事前に TabPage2.Show() などを呼べば回避できます)
回答ありがとうございます。

>ShowDialog を使う際には、Using ブロックを併用しましょう。

分かりました。
実は、.Showdialogしたフォームを閉じた後に、呼び出し元でフォーム上の
Controlにアクセスしたりできるので、メモリの開放はどこで行われるものか
気になっていました。
今後は、Usingを徹底します。

>Load イベントを使いたくない理由を明かしてもらわないと、
>解決策を提示しにくいです…。Shown イベントも駄目なのでしょうか?

すみません。これは、Form1からREFRESH_DGVを呼び出す際に、実際のコードでは
REFRESH_DGVに引数を引き渡して、読み込む内容を可変的に指定したいから
です。もし、LoadやShownイベントでDGVの更新処理を行うとすると、
それより事前にForm2にフィールドとPublicプロパティを設けて、予め引数を渡して
おく・・といった迂遠なコーディングになるのが嫌だったためです。

理由を明記せずすみませんでした。

>DGV.IsHandleCreated が False のときにセットするとそうなるようですね。

なるほど、そういうことだったのですね。Handleについては漠然とした
理解しかありませんが、納得しました。この点が分かっただけでも勉強に
なりました。解決済みとさせて頂きます。
解決済み!
■No31987に返信(kane123さんの記事)
> これは、Form1からREFRESH_DGVを呼び出す際に、実際のコードでは
> REFRESH_DGVに引数を引き渡して、読み込む内容を可変的に指定したいから

Public Sub REFRESH_DGV(…) で引数を渡すのではなく、
Public Sub New(…) のコンストラクタで引き渡すようにして、
Load イベントで初期化するようにしては如何でしょうか。

そうすれば、現在のコードのような
 「呼び出し元は、最初に必ず REFRESH_DGV を呼ばねばならない」
という縛りを回避できるかと思います。
解決済み!

> Public Sub REFRESH_DGV(…) で引数を渡すのではなく、
> Public Sub New(…) のコンストラクタで引き渡すようにして、
> Load イベントで初期化するようにしては如何でしょうか。

なるほど、確かにおっしゃる通りです。
試してみようと思います。ありがとうございます。

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