DataGridViewTextBoxColumnでは、WrapModeプロパティを設定する事により、複数行入力が可能になります。
また、AutoSizeRowModeを設定する事により、行(セル)の高さも調整されます。
ただ、入力時に表示される編集コントロールの高さは、編集コントロールが表示された、時点の行の高さであり、特に新規行など文字列1行分しか見えなくて入力に不便を感じる場合があります。
そこで、DataGridViewTextBoxColumを少しだけ改造してみました。
表示される編集コントロール(TextBox)の高さを設定できるように拡張してみました。
Visual StudioのデザイナでのTextBoxコントロールの Textプロパティの内容の入力時に表示される MultilineStringEditor ようにしようかとも思いましたが、結構大変そうなので簡単に出来る高さを広げるのみとしました。
そのため、DataGridViewのクライアント領域を超えて表示しない物になってしまいました。
クラスの構成は以下の通りです。
DataGridViewTextBoxColumn の派生クラスとして、DataGridViewTextBoxColumnEx。
DataGridViewTextBoxCell の派生クラスとして、DataGridViewTextBoxCellEx。
DataGridViewTextBoxEditingControlはそのまま使用します。
「Ex」と付けるほどの拡張はしていませんが、とりあえず以上のように命名しています。
まずは、DataGridViewTextBoxColumnExクラスから
public class DataGridViewTextBoxColumnEx { private int editingPanelHeight=65; public DataGridViewTextBoxColumnEx() : base() { this.CellTemplate = new DataGridViewTextBoxCellEx(); } // 今回の中心になる、TextBoxの高さを取得または設定するプロパティです。 [Category("配置")] [Browsable(true)] [DefaultValue(65)] [Description("WrapMode プロパティが true の場合に表示される" + "編集コントロールの高さを指定します。")] public int EditingPanelHeight { get { DataGridViewTextBoxCellEx cell = (DataGridViewTextBoxCellEx)this.CellTemplate; return cell.EditingPanelHeight; } set { if (this.editingPanelHeight == value) return; if(this.DataGridView != null) { if( value < this.DataGridView.RowTemplate.Height) return; } else { if(value < 21) return; } //CellTemplateの値を変更する DataGridViewTextBoxCellEx cell = (DataGridViewTextBoxCellEx)this.CellTemplate; cell.EditingPanelHeight = value; if (this.DataGridView == null) return; // 既に登録済みのセルの値を更新 int rowCount = this.DataGridView.RowCount; for (int i = 0; i < rowCount; i++) { DataGridViewRow r = this.DataGridView.Rows.SharedRow(i); DataGridViewTextBoxCellEx rCcell = (DataGridViewTextBoxCellEx)r.Cells[this.Index]; rCell.EditingPanelHeight = value; } } } // EditingPanelHeight プロパティを追加しているので、 // Cloneメソッドをオーバーライド public override object Clone() { DataGridViewTextBoxColumnEx col = (DataGridViewTextBoxColumnEx)base.Clone(); col.editingPanelHeight = this.editingPanelHeight; return col; } // CellTemplateをオーバーライド public override DataGridViewCell CellTemplate { get { return base.CellTemplate; } set { if (value != null && !value.GetType().IsAssignableFrom( typeof(DataGridViewTextBoxCellEx))) { throw new InvalidCastException( "Need DataGridViewTextBoxCellEx object"); } base.CellTemplate = value; } } }
大した事はしていませんが、大きく以下のような事を行っています。
コードを後述する DataGridViewTextBoxCellEx を CellTemplateに登録しています。
デザイナ用に属性を付けた形で EditingPanelHeight プロパティを追加し、それに伴い Clone() メソッドをオーバーライドしています。
次は、DataGridViewTextBoxCellEx です。
実際に 編集用のTextBox の高さの変更はこのクラスで行っています。
public class DataGridViewTextBoxCellEx { private int editingPanelHeight=65; // Cloneメソッドをオーバーライド public override object Clone() { DataGridViewTextBoxCellEx cell = (DataGridViewTextBoxCellEx)base.Clone(); cell.EditingPanelHeight = this.EditingPanelHeight; return cell; } // TextBoxの高さを取得または設定するプロパティです。 public int EditingPanelHeight { get { return editingPanelHeight; } set { editingPanelHeight = value; } } // ホストされる編集コントロールの初期化部をオーバーライドします。 public override void InitializeEditingControl( int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) { base.InitializeEditingControl( rowIndex, initialFormattedValue, dataGridViewCellStyle); if (dataGridViewCellStyle.WrapMode == DataGridViewTriState.True) { // 境界線をセット this.DataGridView.EditingPanel.BorderStyle = BorderStyle.FixedSingle; DataGridViewTextBoxEditingControl ctl = DataGridView.EditingControl as DataGridViewTextBoxEditingControl; // スクロールバーをセット ctl.ScrollBars = ScrollBars.Vertical; } } // 編集パネルの位置とサイズを設定部をオーバーライドします。 public override Rectangle PositionEditingPanel( Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow) { // 複数行である場合 if (cellStyle.WrapMode == DataGridViewTriState.True) { Rectangle rect = cellBounds; rect.Height = editingPanelHeight; // 編集パネルの高さを広げた結果、 // DataGridViewのクライアント領域の下部よりはみ出さないか確認 if(rect.Bottom> this.DataGridView.ClientRectangle.Bottom) { 下部にはみ出す場合はセルの上側に表示する。 rect.Y = rect.Top - editingPanelHeight + cellBounds.Height; // DataGridViewのクライアント領域の上部よりはみ出さないか確認 if (rect.Top < 0) { // 上側表示の結果上部にはみ出す場合は上部ギリギリに調節 rect.Y = 0; } cellClip= cellBounds; } // セルにおけるセルの内容の場所を左上にします。 // 入力開始位置がこれによりパネルの左上からになります cellStyle.Alignment = DataGridViewContentAlignment.TopLeft; cellClip = cellBounds = rect; } return base.PositionEditingPanel( cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow); } }
このクラスの中で編集コントロール(TextBox)の高さの変更と、境界線・スクロールバーを設定しています。
WrapMode が true 以外の場合は EditingPanelHeight プロパティを設定しても、通常の表示がおこなわれます。
実際に DataGridView の「列の編集」から、「DataGridViewTextBoxColumnEx」を列に追加し、入力を行うと以下の図のようになります。
最初に書いた、DataGridViewのクライアント領域を超えて表示できない件は、編集パネル部の高さを、クライアント領域より高くしなければ、どうにか使えると思うのですが...、いわゆる運用の方で....。
0 件のコメント:
コメントを投稿