参照型と値型のEquals
参照型と値型での Object.Equals メソッド の動作の違い。
- 参照型: 同一オブジェクトならば true
- 値型: 保持している値が同じならば true
using System; namespace EqualForValueTypeAndReferenceType { class Program { static void Main(string[] args) { ReferenceType ref1 = new ReferenceType(123); ReferenceType ref2 = new ReferenceType(123); Console.WriteLine("ref1.Equals(ref2) = {0}", ref1.Equals(ref2)); ValueType val1 = new ValueType(123); ValueType val2 = new ValueType(123); Console.WriteLine("val1.Equals(val2) = {0}", val1.Equals(val2)); } } class ReferenceType { private int _intValue; internal ReferenceType(int intValue) { _intValue = intValue; } } struct ValueType { private int _intValue; internal ValueType(int intValue) { _intValue = intValue; } } }
DataGridView の CheckBox に Text も表示する。
DataGridView ではチェックボックスだけが表示されテキストを表示できない。そこでチェックボックスに加えて、テキストも表示できるようにしてみた。
DataGridViewCheckBoxCell クラスを継承し、テキストも表示できる CheckBoxAndTextCell クラスを作成する。
- Text プロパティを追加。
- Paint() で、base.Paint() を呼びチェックボックスを描画したあと、テキストを描画する。
- GetPreferredSize() で、テキストを含めたサイズを返す。この値は自動サイズ設定で使われる。
- Clone() で、追加した Text プロパティの値もコピーする。
using System; using System.Drawing; using System.Windows.Forms; namespace DataGridViewCheckBoxAndTextCell { public class CheckBoxAndTextCell : DataGridViewCheckBoxCell { private const Int32 PadLeft = 2; private const Int32 PadRight = 3; private const Int32 PadTop = 4; private const Int32 PadBottom = 3; private readonly TextFormatFlags FormatFlags = TextFormatFlags.Left | TextFormatFlags.EndEllipsis; private String _text = String.Empty; // チェックボックスの横に表示するテキストを取得、設定する。 public String Text { get { return _text; } set { _text = value; } } public override object DefaultNewRowValue { get { return false; } } protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, Int32 rowIndex, DataGridViewElementStates cellState, Object value, Object formattedValue, String errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) { // DataGridViewCheckBoxCell.Paint で、チェックボックスを描画する。 base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts); // チェックボックスの横のセル内の残りスペースに、テキストを描画する。 Rectangle checkBoxBounds = base.GetContentBounds(graphics, cellStyle, rowIndex); Point textLocation = GetTextLocation(cellBounds, checkBoxBounds); var availableTextSize = GetAvailableTextSize(cellBounds, checkBoxBounds); var availableTextRect = new Rectangle(textLocation, availableTextSize); TextRenderer.DrawText(graphics, Text, cellStyle.Font, availableTextRect, cellStyle.ForeColor, FormatFlags); } private Point GetTextLocation(Rectangle cellBounds, Rectangle contentBounds) { Int32 textX = cellBounds.X + contentBounds.Right + PadLeft; Int32 textY = cellBounds.Y + PadTop; var textLocation = new Point(textX, textY); return textLocation; } private Size GetAvailableTextSize(Rectangle cellBounds, Rectangle contentBounds) { Int32 textWidth = Math.Max(0, cellBounds.Width - contentBounds.Width - PadLeft - PadRight); Int32 textHeight = Math.Max(0, cellBounds.Height - PadBottom); var textSize = new Size(textWidth, textHeight); return textSize; } // カラムの自動サイズ設定に使用する。 protected override Size GetPreferredSize(Graphics graphics, DataGridViewCellStyle cellStyle, Int32 rowIndex, Size constraintSize) { Rectangle checkBoxBounds = base.GetContentBounds(graphics, cellStyle, rowIndex); Size preferredTextSize = TextRenderer.MeasureText(graphics, Text, cellStyle.Font); Int32 contentWidth = checkBoxBounds.Width + preferredTextSize.Width + PadLeft + PadRight; Int32 contentHeight = Math.Max(checkBoxBounds.Height, preferredTextSize.Height + PadTop + PadBottom); var contentSize = new Size(contentWidth, contentHeight); return contentSize; } // 追加した Text プロパティもクローンに含める。 public override object Clone() { var cloneCell = (CheckBoxAndTextCell)base.Clone(); cloneCell.Text = this.Text; return cloneCell; } } }
作成した CheckBoxAndTextCell クラスを DataGridView で使うには、
- 追加するカラムの CellTemplate プロパティに CheckBoxAndTextCell のオブジェクトを設定する。
using System; using System.Windows.Forms; namespace DataGridViewCheckBoxAndTextCell { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { AddColumn("カラム 1"); AddRow("データ行 1"); AddRow("データ行 2"); AddRow("データ行 3"); } private void AddColumn(String headerText) { var viewColumn = new DataGridViewColumn(); viewColumn.HeaderText = headerText; // このカラムのセルは CheckBoxAndTextCell を使う。 viewColumn.CellTemplate = new CheckBoxAndTextCell(); dataGridView1.Columns.Add(viewColumn); } private void AddRow(String text) { Int32 rowIndex = dataGridView1.Rows.Add(); DataGridViewRow viewRow = dataGridView1.Rows[rowIndex]; CheckBoxAndTextCell chkAndTxtCell = (CheckBoxAndTextCell)viewRow.Cells[0]; chkAndTxtCell.Value = false; chkAndTxtCell.Text = text; } } }
コントロールの背景を透過色にする
コントロールの背景を透過色にするには、
- コントロールの BackColor プロパティに Color.Transparent を設定する。
using System; using System.Drawing; using System.Windows.Forms; namespace TransparentLabel { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { checkBox1.BackColor = Color.Transparent; radioButton1.BackColor = Color.Transparent; label1.BackColor = Color.Transparent; button1.BackColor = Color.Transparent; } } }
DataGridView の行や列に区切りを入れる
DataGridView の行や列に区切りを入れるときは、
を設定する。
using System; using System.Windows.Forms; namespace DataGridViewDividerWidthSample { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { for (Int32 columnIndex = 0; columnIndex < 3; ++columnIndex) { String name = String.Format("カラム {0}", columnIndex + 1); dataGridView1.Columns.Add(name, name); } for (Int32 rowIndex = 0; rowIndex < 3; ++rowIndex) { dataGridView1.Rows.Add(); } dataGridView1.Columns[1].DividerWidth = 2; dataGridView1.Rows[1].DividerHeight = 2; } } }
DataGridView の描画が遅いときに気をつけること
DataGridView で、
のプロパティが、自動に設定されているとき、
- 行や列の追加
- セルに値を設定
すると、描画が遅くなる。
以下の例では、50 x 50 で 9.2 秒かかった。
using System; using System.Diagnostics; using System.Windows.Forms; namespace DataGridViewSizeModeAndSpeed { public partial class Form1 : Form { private const int ColumnCount = 50; private const int RowCount = 50; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { var sw = new Stopwatch(); sw.Start(); // サイズ設定が自動のとき、行や列を追加したり、セルに値を設定すると、実行が遅くなる。 dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells; dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; AddColumns(); AddRows(); SetValues(); sw.Stop(); label1.Text = String.Format("所要時間: {0}", sw.Elapsed); } private void AddColumns() { for (int index = 0; index < ColumnCount; ++index) { AddColumn(index + 1); } } private void AddColumn(int columnNumber) { var column = new DataGridViewColumn(); column.Name = columnNumber.ToString(); column.CellTemplate = new DataGridViewTextBoxCell(); dataGridView1.Columns.Add(column); } private void AddRows() { for (int index = 0; index < RowCount; ++index) { dataGridView1.Rows.Add(); } } private void SetValues() { for (int columnIndex = 0; columnIndex < ColumnCount; ++columnIndex) { for (int rowIndex = 0; rowIndex < RowCount; ++rowIndex) { String value = String.Format("{0}-{1}", columnIndex + 1, rowIndex + 1); dataGridView1[columnIndex, rowIndex].Value = value; } } } } }
順番を、
- 自動サイズ設定しない。
- 行や列を追加、セルに値を設定。
- 自動サイズ設定する。
に変更すると、描画時間は 0.15 秒になった。
private void Form1_Load(object sender, EventArgs e) { var sw = new Stopwatch(); sw.Start(); // 行や列を追加したり、セルに値を設定するときは、自動サイズ設定しない。 dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None; dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing; AddColumns(); AddRows(); SetValues(); // 自動でサイズを設定するのは、行や列を追加したり、セルに値を設定した後にする。 dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells; dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; sw.Stop(); label1.Text = String.Format("所要時間: {0}", sw.Elapsed); }