- - PR -
仮想モードのDataGridViewでの描画について
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2006-09-14 21:41
他の掲示板でも質問したのですが、回答が全く得られないのでこちらでもお願いします。
仮想モードのDataGridViewでCellValueNeeded,CellValuePushedイベントを実装しても、 DataGridViewを通さずにデータに設定した値をDataGridViewに反映するにはどうしたらよいのでしょうか? 仮想モードでなければ、データを直接いじってもすぐに反映されるのですが、 仮想モードではなぜかCellValueNeeded,CellValuePushedイベントを設定しても反映されません。 次のように、ボタンを押すと直接データの値を設定する簡単な例を2つ書いてみました。 ボタンを押した後,マウスを動かすなどした後ではCellValueNeededは発生していますが、 なぜ反映されないのでしょうか??? ご存知の方いらっしゃいましたらよろしくお願いします。 ’例1、Button1つと、DataGridView1つをフォームに追加 Public Class Form1 Private _list As List(Of String) = New List(Of String) Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.DataGridView1.VirtualMode = True Me.DataGridView1.Columns.Add("テスト", "テスト") Me.DataGridView1.Rows.AddCopies(0, 100) For i As Integer = 0 To 100 _list.Add(i.ToString) Next End Sub Private Sub DataGridView1_CellValueNeeded(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValueEventArgs) Handles DataGridView1.CellValueNeeded e.Value = _list(e.RowIndex) Debug.Print(e.Value.ToString) End Sub Private Sub DataGridView1_CellValuePushed(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValueEventArgs) Handles DataGridView1.CellValuePushed _list(e.RowIndex) = e.Value.ToString End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click _list(0) = "直接設定された値" End Sub End Class ’例2 ’Public Class Form1 Private _button As Button Private _inheritedDataGridView As InheritedDataGridView Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load _button = New Button _inheritedDataGridView = New InheritedDataGridView(_button) Me.Controls.Add(_button) Me.Controls.Add(_inheritedDataGridView) _inheritedDataGridView.Top = _button.Top + _button.Height End Sub End Class Public Class InheritedDataGridView Inherits DataGridView Private WithEvents _btn As Button Private _list As List(Of String) = New List(Of String) Public Sub New(ByVal button As Button) _btn = button Me.VirtualMode = True Me.Columns.Add("テスト", "テスト") Me.Rows.AddCopies(0, 100) For i As Integer = 0 To 100 _list.Add(i.ToString) Next End Sub Private Sub _btn_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles _btn.Click _list(0) = "直接代入された値" MyBase.OnCellValueNeeded(New DataGridViewCellValueEventArgs(0, 0)) End Sub Private Sub InheritedDataGridView_CellValueNeeded(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValueEventArgs) Handles Me.CellValueNeeded e.Value = _list(e.RowIndex) End Sub Private Sub InheritedDataGridView_CellValuePushed(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValueEventArgs) Handles Me.CellValuePushed _list(e.RowIndex) = e.Value.ToString End Sub End Class | ||||
|
投稿日時: 2006-09-15 00:49
今実行できる環境がないので記憶をたどっていますが、
> Me.DataGridView1.Rows.AddCopies(0, 100) でなく、 Me.DataGridView1.VirtualRowCount = 100 としたらどうなりますか? たしか、Virtualなんとか というプロパティで行数を指定したような気がします。 私は Rows.AddCopies は使いませんでした。 | ||||
|
投稿日時: 2006-09-15 01:44
OnHogehoge メソッドを誤解しているような気がします。
OnHogehoge メソッドは Hogehoge イベントを発生させると説明されますが、これは要するに Hogehoge イベントに登録されたイベントハンドラを実行させる、と言う意味であってそれ以上ではありません。 分かりやすい例だと OnMouseMove 。これを呼び出してもマウスポインタが勝手に動いたりはしませんよね? 同様に、OnCellValueNeeded を呼び出したからと言って勝手に再描画されるわけではありません。 再描画が必要になった時に CellValueNeeded も呼ばれるんですから、データを変更した際に強制的に再描画を行えば良いわけです。 DataGridView には、Control から継承する再描画メソッドの他、色々と用意されています。 多すぎて確認するのが大変だという向きは、Windows フォーム DataGridView コントロールでの仮想モード を見てみるのも良いかも知れません。
RowCount プロパティですね。 | ||||
|
投稿日時: 2006-09-15 09:16
InvalidateCellメソッドでできました!
RowCountも知らなかったのでとても参考になりました。 ありがとうございました。 | ||||
|
投稿日時: 2006-09-15 10:06
InvalidateCell は強制的に再描画するものですから、
1回余分に描画を行っていることになるかもしれませんね。 今回の質問とは直接関係はありませんが、 仮想モード時はちょっと操作しただけで描画イベントが発生しています。 ですから、CellValueNeeded のような値に関するイベントの処理は できるだけ「軽い」内容にしておく必要があります。 Debug.WriteLine をいくつか仕込むだけでも「もっさり」することもあります。 | ||||
|
投稿日時: 2006-09-15 16:11
>InvalidateCell は強制的に再描画するものですから、
>1回余分に描画を行っていることになるかもしれませんね。 他にもっといい方法がある、ということですか? >仮想モード時はちょっと操作しただけで描画イベントが発生しています。 >ですから、CellValueNeeded のような値に関するイベントの処理は >できるだけ「軽い」内容にしておく必要があります。 仮想モードにしても、描画は遅いですね。 25列×25行程度の表示でオートサイズはしていません。 CellValueNeededでの処理は、行インデックスと行インデックスのチェックだけですが、 スクロールするとパラパラ漫画のように描画処理が目に見えます。 (実用には問題にならない程度ですが、気になります・・・) これは仕様かとあきらめていましたが、 解決する方法はありますか? [ メッセージ編集済み 編集者: hei 編集日時 2006-09-15 16:16 ] | ||||
|
投稿日時: 2006-09-15 16:35
今手元にソースがないのですが、覚えている限り InvalidateCell は使っていません。
CellValueNeeded などの値要求イベントだけで表示していました。 描画自体にどれほど違いがあるかどうかわかりませんが、 まず、列オブジェクトに対してテンプレートセルを設定しました。 単純に Columns.Add としただけでは、テンプレートは設定されていないような気がします。 MSDNの仮想モードに関するページにも できるだけテンプレートを使うように推奨されています。 それから、CellValueNeeded 内の Debug.Print(e.Value.ToString) は消している状態でしょうか。 あるとないとでもデバッグ実行上の描画速度は変わると思います。 | ||||
|
投稿日時: 2006-09-15 17:21
全ての列に
CellTemplate = New DataGridViewTextBoxCell してみましたが、体感的にはあまり変わりませんでした。 Debug.Print(e.Value.ToString) はありません。 |