列の完成
これでセル部分はできあがりです。この列の作成の仕上げとして、DataGridViewBarGraphColumnクラスに既定のコンストラクタを追加し、そのコードを編集して列のCellTemplate
プロパティを設定し、列を読み取り専用にします。
Public Class DataGridViewBarGraphColumn Inherits DataGridViewColumn Public Sub New() Me.CellTemplate = _ New DataGridViewBarGraphCell() Me.ReadOnly = True End Sub Public MaxValue As Long Private needsRecalc As Boolean = True Public Sub CalcMaxValue() End Sub End Class
public class DataGridViewBarGraphColumn : DataGridViewColumn { public DataGridViewBarGraphColumn() { this.CellTemplate = new DataGridViewBarGraphCell(); this.ReadOnly = true; } public long MaxValue; private bool needsRecalc = true; public void CalcMaxValue(){} }
最後に、列の最大値の計算処理を作成します。列自体は親コントロールのイベントにフックできないので、簡単な方法として、セルの描画時に各セルから呼び出すプロシージャ(CalcMaxValue)を使用します。本当は各セルが描画されるごとに最大値を計算しなくてもよいのですが、すべてのデータが読み込まれるまで実行されないコードを記述する場所として、これ以外に単純明白なわかりやすい場所がないので、この方法にします(この問題を解決する別の方法もあるかもしれませんが、ここに示した方法は比較的無難であり、また正しく動作します)。
CalcMaxValueプロシージャを編集し、現在の列のすべての値を調べて最大値を追跡するようにします。プロシージャの最後でneedsRecalcフィールドをfalseに設定し、それ以降のプロシージャ呼び出しで最大値を再計算しないようにします。
Public Sub CalcMaxValue() If needsRecalc Then Dim colIndex As Integer = Me.DisplayIndex For rowIndex As Integer = 0 To _ Me.DataGridView.Rows.Count - 1 Dim row As DataGridViewRow = _ Me.DataGridView.Rows(rowIndex) MaxValue = Math.Max(MaxValue, _ CLng(row.Cells(colIndex).Value)) Next needsRecalc = False End If End Sub
public void CalcMaxValue() { if (needsRecalc) { int colIndex = this.DisplayIndex; for (int rowIndex = 0; rowIndex < this.DataGridView.Rows.Count; rowIndex++) { DataGridViewRow row = this.DataGridView.Rows[rowIndex]; MaxValue = Math.Max(MaxValue, Convert.ToInt64(row.Cells[colIndex].Value)); } needsRecalc = false; } }
needsRecalcフィールドをパブリックにして他の呼び出し元からリセットできるようにすることもできます。たとえば、ユーザーが列の値を変更できるようにする場合、最大値の再計算を強制的に実行できるようにする必要があります。親グリッドのセル変更イベントをトラップして、対象の列の値が変更された場合に再計算を強制実行できるようにすることも可能です。これは読者への宿題にしましょう。
これで完成です。この列のセルテンプレートにDataGridViewBarGraphCellクラスを使用することを指定し、この列が読み取り専用であることを指定し、列の最大値を計算するコードを追加しました。
フォームのデザインビューに戻り、DataGridViewコントロールの各列を設定します。図3のように、UnitsInStock列(または使用する他の数値列)に、列の種類としてDataGridViewBarGraphColumnを選択します。[OK]をクリックし、プロジェクトを保存して実行します。問題なく動作すれば、図1のように、DataGridViewに横棒グラフ列が表示されるはずです。
もちろん、もっといろいろなカスタマイズも可能です。Button、CheckBox、ComboBox、Image、Linkといったコントロールを表示する列など、さまざまなタイプを継承できます。適切なクラスを継承すれば、ほとんどの処理が自動的に行われます。また、各基本クラスにはオーバーライド可能なプロテクトメソッドが多数あり、これによって、求めるとおりのセルタイプを作成できます。このようなプロジェクトでは、System.Drawing.Drawing2D名前空間のクラスの知識は非常に役に立ちます。このサンプルで使用したクラスをこれまで使ったことがない場合は、この機会に調べてみてください。きっとまた利用することになるでしょう。