Simple Examples => http://csharp.net-informations.com/datagridview/csharp-datagridview-readonly-column.htm
MSDN Examples => http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview(v=vs.110).aspx
Class generator for DataGridView => A class for simplify Databinding.
DataGridView use SelectionChanges(...) for row selection.
DataGridViewComboBoxColumn =>
- DataSource = object;
- DisplayMember = "";
- ValueMember = "";
- DataPropertyName = "";
DataGridViewColumn custom is complex, especially RadioButtons.
Custom Columns:
- Nullable DateTimePicker -> allow empty/null value for datasource.
- RadioButtoms -> List of radioButtons vertically listed.
Custom Method => How to: Host Controls in Windows Forms DataGridView Cells
http://msdn.microsoft.com/en-us/library/vstudio/7tas5c80(v=vs.100).aspx
http://msdn.microsoft.com/en-US/library/aa730881(v=vs.80).aspx
Error Display => Cell.ErrorTet; Row.ErrorText
using System; using System.Windows.Forms; public class CalendarColumn : DataGridViewColumn { public CalendarColumn() : base(new CalendarCell()) { } public override DataGridViewCell CellTemplate { get { return base.CellTemplate; } set { // Ensure that the cell used for the template is a CalendarCell. if (value != null && !value.GetType().IsAssignableFrom(typeof(CalendarCell))) { throw new InvalidCastException("Must be a CalendarCell"); } base.CellTemplate = value; } } } public class CalendarCell : DataGridViewTextBoxCell { public CalendarCell() : base() { // Use the short date format. this.Style.Format = "d"; } public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) { // Set the value of the editing control to the current cell value. base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle); CalendarEditingControl ctl = DataGridView.EditingControl as CalendarEditingControl; // Use the default row value when Value property is null. if (this.Value == null) { ctl.Value = (DateTime)this.DefaultNewRowValue; } else { ctl.Value = (DateTime)this.Value; } } public override Type EditType { get { // Return the type of the editing control that CalendarCell uses. return typeof(CalendarEditingControl); } } public override Type ValueType { get { // Return the type of the value that CalendarCell contains. return typeof(DateTime); } } public override object DefaultNewRowValue { get { // Use the current date and time as the default value. return DateTime.Now; } } } class CalendarEditingControl : DateTimePicker, IDataGridViewEditingControl { DataGridView dataGridView; private bool valueChanged = false; int rowIndex; public CalendarEditingControl() { this.Format = DateTimePickerFormat.Short; } // Implements the IDataGridViewEditingControl.EditingControlFormattedValue // property. public object EditingControlFormattedValue { get { return this.Value.ToShortDateString(); } set { if (value is String) { try { // This will throw an exception of the string is // null, empty, or not in the format of a date. this.Value = DateTime.Parse((String)value); } catch { // In the case of an exception, just use the // default value so we're not left with a null // value. this.Value = DateTime.Now; } } } } // Implements the // IDataGridViewEditingControl.GetEditingControlFormattedValue method. public object GetEditingControlFormattedValue( DataGridViewDataErrorContexts context) { return EditingControlFormattedValue; } // Implements the // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method. public void ApplyCellStyleToEditingControl( DataGridViewCellStyle dataGridViewCellStyle) { this.Font = dataGridViewCellStyle.Font; this.CalendarForeColor = dataGridViewCellStyle.ForeColor; this.CalendarMonthBackground = dataGridViewCellStyle.BackColor; } // Implements the IDataGridViewEditingControl.EditingControlRowIndex // property. public int EditingControlRowIndex { get { return rowIndex; } set { rowIndex = value; } } // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey // method. public bool EditingControlWantsInputKey( Keys key, bool dataGridViewWantsInputKey) { // Let the DateTimePicker handle the keys listed. switch (key & Keys.KeyCode) { case Keys.Left: case Keys.Up: case Keys.Down: case Keys.Right: case Keys.Home: case Keys.End: case Keys.PageDown: case Keys.PageUp: return true; default: return !dataGridViewWantsInputKey; } } // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit // method. public void PrepareEditingControlForEdit(bool selectAll) { // No preparation needs to be done. } // Implements the IDataGridViewEditingControl // .RepositionEditingControlOnValueChange property. public bool RepositionEditingControlOnValueChange { get { return false; } } // Implements the IDataGridViewEditingControl // .EditingControlDataGridView property. public DataGridView EditingControlDataGridView { get { return dataGridView; } set { dataGridView = value; } } // Implements the IDataGridViewEditingControl // .EditingControlValueChanged property. public bool EditingControlValueChanged { get { return valueChanged; } set { valueChanged = value; } } // Implements the IDataGridViewEditingControl // .EditingPanelCursor property. public Cursor EditingPanelCursor { get { return base.Cursor; } } protected override void OnValueChanged(EventArgs eventargs) { // Notify the DataGridView that the contents of the cell // have changed. valueChanged = true; this.EditingControlDataGridView.NotifyCurrentCellDirty(true); base.OnValueChanged(eventargs); } } public class Form1 : Form { private DataGridView dataGridView1 = new DataGridView(); [STAThreadAttribute()] public static void Main() { Application.Run(new Form1()); } public Form1() { this.dataGridView1.Dock = DockStyle.Fill; this.Controls.Add(this.dataGridView1); this.Load += new EventHandler(Form1_Load); this.Text = "DataGridView calendar column demo"; } private void Form1_Load(object sender, EventArgs e) { CalendarColumn col = new CalendarColumn(); this.dataGridView1.Columns.Add(col); this.dataGridView1.RowCount = 5; foreach (DataGridViewRow row in this.dataGridView1.Rows) { row.Cells[0].Value = DateTime.Now; } } }
You can add a CheckBox into the DataGridView, and make it stay on the column header cell by setting its location, handle its CheckedChanged event to make all the DataGridViewCheckBox cells with the same status as the CheckBox on the header cell, something like this:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { c1 = new DataGridViewCheckBoxColumn(); c1.Name = "selection"; c1.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; this.dataGridView1.Columns.Add(c1); this.dataGridView1.Rows.Add(); this.dataGridView1.Rows.Add(); this.dataGridView1.Rows.Add(); this.dataGridView1.Rows.Add(); ckBox = new CheckBox(); //Get the column header cell bounds Rectangle rect = this.dataGridView1.GetCellDisplayRectangle(0, -1, true); ckBox.Size = new Size(18, 18); //Change the location of the CheckBox to make it stay on the header ckBox.Location = rect.Location; ckBox.CheckedChanged += new EventHandler(ckBox_CheckedChanged); //Add the CheckBox into the DataGridView this.dataGridView1.Controls.Add(ckBox); } DataGridViewCheckBoxColumn c1; CheckBox ckBox; void ckBox_CheckedChanged(object sender, EventArgs e) { for (int j = 0; j < this.dataGridView1.RowCount; j++) { this.dataGridView1[0, j].Value = this.ckBox.Checked; } this.dataGridView1.EndEdit(); } }
Use ListView control for editing cell in DataGridView
http://www.codeproject.com/Tips/588733/Use-ListView-control-for-editing-cell-in-DataGridV
DataGridView Anchor:
dgvNursingOccurs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right)));
DataGridView.CellParsing Event
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.cellparsing(v=vs.110).aspx
// Handling CellParsing allows one to accept user input, then map it to a different // internal representation. private void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e) { if (this.dataGridView1.Columns[e.ColumnIndex].Name == "Release Date") { if (e != null) { if (e.Value != null) { try { // Map what the user typed into UTC. e.Value = DateTime.Parse(e.Value.ToString()).ToUniversalTime(); // Set the ParsingApplied property to // Show the event is handled. e.ParsingApplied = true; } catch (FormatException) { // Set to false in case another CellParsing handler // wants to try to parse this DataGridViewCellParsingEventArgs instance. e.ParsingApplied = false; } } } } }
DataGridView.CellFormatting Event
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { // If the column is the Artist column, check the // value. if (this.dataGridView1.Columns[e.ColumnIndex].Name == "Artist") { if (e.Value != null) { // Check for the string "pink" in the cell. string stringValue = (string)e.Value; stringValue = stringValue.ToLower(); if ((stringValue.IndexOf("pink") > -1)) { e.CellStyle.BackColor = Color.Pink; } } } else if (this.dataGridView1.Columns[e.ColumnIndex].Name == "Release Date") { ShortFormDateFormat(e); } } //Even though the date internaly stores the year as YYYY, using formatting, the //UI can have the format in YY. private static void ShortFormDateFormat(DataGridViewCellFormattingEventArgs formatting) { if (formatting.Value != null) { try { System.Text.StringBuilder dateString = new System.Text.StringBuilder(); DateTime theDate = DateTime.Parse(formatting.Value.ToString()); dateString.Append(theDate.Month); dateString.Append("/"); dateString.Append(theDate.Day); dateString.Append("/"); dateString.Append(theDate.Year.ToString().Substring(2)); formatting.Value = dateString.ToString(); formatting.FormattingApplied = true; } catch (FormatException) { // Set to false in case there are other handlers interested trying to // format this DataGridViewCellFormattingEventArgs instance. formatting.FormattingApplied = false; } } }
DataGridView Cell CheckBox binding to DataSet column with value 1/0:
private void dgvNursingOccurs_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (this.dgvNursingOccurs.Columns[e.ColumnIndex].Name == "NursingCheckFlag") { if (e.Value != null) { if (e.Value.ToString() == "1") { //NursingCheckFlag.Selected = true; e.Value = true; } else { //NursingCheckFlag.Selected = false; e.Value = false; } } } } private void dgvNursingOccurs_CellParsing(object sender, DataGridViewCellParsingEventArgs e) { if (this.dgvNursingOccurs.Columns[e.ColumnIndex].Name == "NursingCheckFlag") { if (e != null) { if (e.Value != null) { if ((bool)e.Value == true) { e.Value = "1"; e.ParsingApplied = true; } else { e.Value = "0"; e.ParsingApplied = true; } } } } }
You can use the CellValidating event and the e.FormattedValue will have the changed value. If you perform some check, and dont want the value to update, set e.Cancel to true.
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) { dataGridView1.Rows[e.RowIndex].ErrorText = ""; int newInteger; // Don't try to validate the 'new row' until finished // editing since there // is not any point in validating its initial value. if (dataGridView1.Rows[e.RowIndex].IsNewRow) { return; } if (!int.TryParse(e.FormattedValue.ToString(), out newInteger) || newInteger < 0) { e.Cancel = true; dataGridView1.Rows[e.RowIndex].ErrorText = "the value must be a non-negative integer"; } }
you can use FalseValue and TrueValue of your gridview's checkboxcolumn's property so as per your value 0 and 1 it will change itseld
It Works.
DataGridViewCheckboxCellFilter.cs: using System.Windows.Forms; namespace MyNamespace { public class DataGridViewCheckboxCellFilter : DataGridViewCheckBoxCell { public DataGridViewCheckboxCellFilter() : base() { this.FalseValue = 0; this.TrueValue = 1; this.Value = TrueValue; } } } After this, on your GridView, where you add the checkbox-column, you do: // add checkboxes DataGridViewCheckBoxColumn col_chkbox = new DataGridViewCheckBoxColumn(); { col_chkbox.HeaderText = "X"; col_chkbox.Name = "checked"; col_chkbox.CellTemplate = new DataGridViewCheckboxCellFilter(); } this.Columns.Add(col_chkbox); And that's it! Everytime your checkboxes get added in a new row, they'll be set to true. Enjoy!
DataGridViewRow ReadOnly ?????
Trouble => row ReadOnly doesn't work in somewhere
private void dgvNursingOccurs_RowEnter(object sender, DataGridViewCellEventArgs e) { DataGridViewRow row = dgvNursingOccurs.CurrentRow; if (row == null) { return; } if (row.Cells["NursingCheckFlag"].Value.ToString() == gIS_CHECKYes) { row.ReadOnly = true; MessageBox.Show("该行数据不能修改。"); } }
How to merge two column headers of a datagridview
http://www.codeproject.com/Questions/472361/Howplustoplusmergeplustwopluscolumnplusheadersplus
private void FormMergeColumns_Load(object sender, EventArgs e) { this.dataGridView1.Columns.Add("JanWin", "Win"); this.dataGridView1.Columns.Add("JanLoss", "Loss"); this.dataGridView1.Columns.Add("FebWin", "Win"); this.dataGridView1.Columns.Add("FebLoss", "Loss"); this.dataGridView1.Columns.Add("MarWin", "Win"); this.dataGridView1.Columns.Add("MarLoss", "Loss"); for (int j = 0; j < this.dataGridView1.ColumnCount; j++) { this.dataGridView1.Columns[j].Width = 45; } this.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing; this.dataGridView1.ColumnHeadersHeight = this.dataGridView1.ColumnHeadersHeight * 2; this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter; this.dataGridView1.CellPainting += new DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting); this.dataGridView1.Paint += new PaintEventHandler(dataGridView1_Paint); } void dataGridView1_Paint(object sender, PaintEventArgs e) { string[] monthes = { "January", "February", "March" }; for (int j = 0; j < 6; ) { //get the column header cell Rectangle r1 = this.dataGridView1.GetCellDisplayRectangle(j, -1, true); r1.X += 1; r1.Y += 1; r1.Width = r1.Width * 2 - 2; r1.Height = r1.Height / 2 - 2; e.Graphics.FillRectangle(new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1); StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; e.Graphics.DrawString(monthes[j / 2], this.dataGridView1.ColumnHeadersDefaultCellStyle.Font, new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor), r1, format); j += 2; } } void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.RowIndex == -1 && e.ColumnIndex > -1) { e.PaintBackground(e.CellBounds, false); Rectangle r2 = e.CellBounds; r2.Y += e.CellBounds.Height / 2; r2.Height = e.CellBounds.Height / 2; e.PaintContent(r2); e.Handled = true; } }
Vertical Header Text
StringFormat l_objformat = new StringFormat(); /////////////////////////////////////////////////////////////// if (e.RowIndex == -1 && e.ColumnIndex > -1) { Rectangle r2 = e.CellBounds; r2.Y += e.CellBounds.Height / 2; r2.Height = e.CellBounds.Height / 2; e.PaintBackground(r2, true); e.PaintContent(r2); ////////////////////////////////////////////////////////////////// e.PaintBackground(e.ClipBounds, true); Rectangle rect = this.dataGridView1.GetColumnDisplayRectangle (e.ColumnIndex, true); Size titleSize = TextRenderer.MeasureText(e.Value.ToString(), e.CellStyle.Font); if (this.dataGridView1.ColumnHeadersHeight < titleSize.Width) this.dataGridView1.ColumnHeadersHeight = titleSize.Width; rect.X += e.CellBounds.Width/2; rect.Y +=dataGridView1.ColumnHeadersHeight/2; l_objformat.FormatFlags = StringFormatFlags.DirectionVertical; e.Graphics.DrawString(e.Value.ToString(), e.CellStyle.Font, Brushes.Red, rect, l_objformat); e.Handled = true;//This is required, else the original painting of the data grid view overwrites the changes. }
How can i merge DataGridView Rows (Cells with Equal Values)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace CustomDataGridView { public partial class Formxx : Form { DataGridView dataGrid; DataSet dataSet; Button button; private List<string> MergedRowsInFirstColumn = new List<string>(); private bool readyToMerge = false; public Formxx() { InitializeComponent(); CreateGridAndButton(); } private void CreateGridAndButton() { dataGrid = new DataGridView(); dataSet = new DataSet(); dataGrid.Height = this.Height - 100; dataGrid.Dock = DockStyle.Top; dataGrid.ReadOnly = true; dataGrid.AllowUserToAddRows = false; dataGrid.AllowUserToResizeRows = false; dataGrid.RowHeadersVisible = false; this.dataGrid.Paint += new PaintEventHandler(dataGrid_Paint); this.Controls.Add(this.dataGrid); button = new Button(); button.Text = "Merge"; button.Dock = DockStyle.Bottom; button.Click += new System.EventHandler(this.button_Click); this.Controls.Add(this.button); DataTable tbl_main = new DataTable("tbl_main"); tbl_main.Columns.Add("Manufacture"); tbl_main.Columns.Add("Name"); tbl_main.Columns.Add("CPU"); tbl_main.Columns.Add("RAM"); tbl_main.Columns.Add("Price"); DataRow row; row = tbl_main.NewRow(); row["Manufacture"] = "Dell"; row["Name"] = "Inspiron 1525"; row["CPU"] = "T7250"; row["RAM"] = "2048 MB"; row["Price"] = "$654"; tbl_main.Rows.Add(row); row = tbl_main.NewRow(); row["Manufacture"] = "Dell"; row["Name"] = "Inspiron 1525"; row["CPU"] = "T5750"; row["RAM"] = "2048 MB"; row["Price"] = "$690"; tbl_main.Rows.Add(row); row = tbl_main.NewRow(); row["Manufacture"] = "Dell"; row["Name"] = "Studio 1535"; row["CPU"] = "T5750"; row["RAM"] = "2048 MB"; row["Price"] = "$735"; tbl_main.Rows.Add(row); row = tbl_main.NewRow(); row["Manufacture"] = "Dell"; row["Name"] = "Vostro 1510"; row["CPU"] = "T5870"; row["RAM"] = "2048 MB"; row["Price"] = "$724"; tbl_main.Rows.Add(row); row = tbl_main.NewRow(); row["Manufacture"] = "HP"; row["Name"] = "530"; row["CPU"] = "T5200"; row["RAM"] = "1024 MB"; row["Price"] = "$545"; tbl_main.Rows.Add(row); row = tbl_main.NewRow(); row["Manufacture"] = "HP"; row["Name"] = "6720s"; row["CPU"] = "T5670"; row["RAM"] = "1024 MB"; row["Price"] = "$637"; tbl_main.Rows.Add(row); row = tbl_main.NewRow(); row["Manufacture"] = "HP"; row["Name"] = "Pavilion dv9233"; row["CPU"] = "T5670"; row["RAM"] = "1024 MB"; row["Price"] = "$780"; tbl_main.Rows.Add(row); dataSet.Tables.Add(tbl_main); dataGrid.DataSource = dataSet; dataGrid.DataMember = "tbl_main"; } private void dataGrid_Paint(object sender, PaintEventArgs e) { if (readyToMerge) { Merge(); } } private void button_Click(object sender, EventArgs e) { Merge(); readyToMerge = true; } private bool isSelectedCell(int[] Rows, int ColumnIndex) { if (dataGrid.SelectedCells.Count > 0) { for (int iCell = Rows[0]; iCell <= Rows[1]; iCell++) { for (int iSelCell = 0; iSelCell < dataGrid.SelectedCells.Count; iSelCell++) { if (dataGrid.Rows[iCell].Cells[ColumnIndex] == dataGrid.SelectedCells[iSelCell]) { return true; } } } return false; } else { return false; } } private void Merge() { int[] RowsToMerge = new int[2]; RowsToMerge[0] = -1; //Merge first column at first for (int i = 0; i < dataSet.Tables["tbl_main"].Rows.Count - 1; i++) { if (dataSet.Tables["tbl_main"].Rows[i]["Manufacture"] == dataSet.Tables["tbl_main"].Rows[i + 1]["Manufacture"]) { if (RowsToMerge[0] == -1) { RowsToMerge[0] = i; RowsToMerge[1] = i + 1; } else { RowsToMerge[1] = i + 1; } } else { MergeCells(RowsToMerge[0], RowsToMerge[1], dataGrid.Columns["Manufacture"].Index, isSelectedCell(RowsToMerge, dataGrid.Columns["Manufacture"].Index) ? true : false); CollectMergedRowsInFirstColumn(RowsToMerge[0], RowsToMerge[1]); RowsToMerge[0] = -1; } if (i == dataSet.Tables["tbl_main"].Rows.Count - 2) { MergeCells(RowsToMerge[0], RowsToMerge[1], dataGrid.Columns["Manufacture"].Index, isSelectedCell(RowsToMerge, dataGrid.Columns["Manufacture"].Index) ? true : false); CollectMergedRowsInFirstColumn(RowsToMerge[0], RowsToMerge[1]); RowsToMerge[0] = -1; } } if (RowsToMerge[0] != -1) { MergeCells(RowsToMerge[0], RowsToMerge[1], dataGrid.Columns["Manufacture"].Index, isSelectedCell(RowsToMerge, dataGrid.Columns["Manufacture"].Index) ? true : false); RowsToMerge[0] = -1; } //merge all other columns for (int iColumn = 1; iColumn < dataSet.Tables["tbl_main"].Columns.Count - 1; iColumn++) { for (int iRow = 0; iRow < dataSet.Tables["tbl_main"].Rows.Count - 1; iRow++) { if ((dataSet.Tables["tbl_main"].Rows[iRow][iColumn] == dataSet.Tables["tbl_main"].Rows[iRow + 1][iColumn]) && (isRowsHaveOneCellInFirstColumn(iRow, iRow + 1))) { if (RowsToMerge[0] == -1) { RowsToMerge[0] = iRow; RowsToMerge[1] = iRow + 1; } else { RowsToMerge[1] = iRow + 1; } } else { if (RowsToMerge[0] != -1) { MergeCells(RowsToMerge[0], RowsToMerge[1], iColumn, isSelectedCell(RowsToMerge, iColumn) ? true : false); RowsToMerge[0] = -1; } } } if (RowsToMerge[0] != -1) { MergeCells(RowsToMerge[0], RowsToMerge[1], iColumn, isSelectedCell(RowsToMerge, iColumn) ? true : false); RowsToMerge[0] = -1; } } } private bool isRowsHaveOneCellInFirstColumn(int RowId1, int RowId2) { foreach (string rowsCollection in MergedRowsInFirstColumn) { string[] RowsNumber = rowsCollection.Split(';'); if ((isStringInArray(RowsNumber, RowId1.ToString())) && (isStringInArray(RowsNumber, RowId2.ToString()))) { return true; } } return false; } private bool isStringInArray(string[] Array, string value) { foreach (string item in Array) { if (item == value) { return true; } } return false; } private void CollectMergedRowsInFirstColumn(int RowId1, int RowId2) { string MergedRows = String.Empty; for (int i = RowId1; i <= RowId2; i++) { MergedRows += i.ToString() + ";"; } MergedRowsInFirstColumn.Add(MergedRows.Remove(MergedRows.Length - 1, 1)); } private void MergeCells(int RowId1, int RowId2, int Column, bool isSelected) { Graphics g = dataGrid.CreateGraphics(); Pen gridPen = new Pen(dataGrid.GridColor); //Cells Rectangles Rectangle CellRectangle1 = dataGrid.GetCellDisplayRectangle(Column, RowId1, true); Rectangle CellRectangle2 = dataGrid.GetCellDisplayRectangle(Column, RowId2, true); int rectHeight = 0; string MergedRows = String.Empty; for (int i = RowId1; i <= RowId2; i++) { rectHeight += dataGrid.GetCellDisplayRectangle(Column, i, false).Height; } Rectangle newCell = new Rectangle(CellRectangle1.X, CellRectangle1.Y, CellRectangle1.Width, rectHeight); g.FillRectangle(new SolidBrush(isSelected ? dataGrid.DefaultCellStyle.SelectionBackColor : dataGrid.DefaultCellStyle.BackColor), newCell); g.DrawRectangle(gridPen, newCell); g.DrawString(dataGrid.Rows[RowId1].Cells[Column].Value.ToString(), dataGrid.DefaultCellStyle.Font, new SolidBrush(isSelected ? dataGrid.DefaultCellStyle.SelectionForeColor : dataGrid.DefaultCellStyle.ForeColor), newCell.X + newCell.Width / 3, newCell.Y + newCell.Height / 3); } } }
ControlPaint Class
Provides methods used to paint common Windows controls and their elements. This class cannot be inherited.
http://msdn.microsoft.com/en-us/library/system.windows.forms.controlpaint.aspx
Multiple RadioButtons
http://msdn.microsoft.com/en-us/library/aa730882(v=vs.80).aspx
How to: Customize Cells and Columns in the Windows Forms DataGridView Control by Extending Their Behavior and Appearance
http://msdn.microsoft.com/en-us/library/7fb61s43.aspx
How to: Host Controls in Windows Forms DataGridView Cells
http://msdn.microsoft.com/en-us/library/7tas5c80.aspx
DataGridView => Add control to cells
Rectangle rect = dataGridView1.GetCellDisplayRectangle(1, 0, true); //Rectangle rect = dataGridView1. Button btn = new Button(); btn.Location = new Point(rect.X-1, rect.Y-1); btn.Size = new Size(rect.Width+2, rect.Height+2); dataGridView1.Controls.Add(btn);
Add tooltip to datagridview cells in windows application
private void myDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { int columnIndex = 1; // Assign the column index you want to add tooltip if (e.ColumnIndex == dataGridView1.Columns[columnIndex].Index) { //Get the datagridview cell DataGridViewCell cell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]; if (cell != null) { //You can add any tooltip text in below example I am taking the cell value itself to show as tooltip cell.ToolTipText = "cell.ToolTipText"; // dataGridView1.Rows[e.RowIndex].Cells[columnIndex].Value.ToString(); } } }
Ensuring text wraps in a dataGridView column
private int _rowMaxHeight = 0; private int _rowDefaultHeight = 0; private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.Value == null || e.RowIndex < 0) { // The WordWrap code is ony executed if requested the cell has a value, // and if this is not the heading row. return; } if (e.ColumnIndex == 0) { // Resetting row max height on each row's first cell _rowMaxHeight = 0; if (_rowDefaultHeight == 0) { /* The default DataGridView row height is saved when the first cell * inside the first row is populated the first time. This is later * used as the minimum row height, to avoid * smaller-than-default rows. */ _rowDefaultHeight = dataGridView1.Rows[e.RowIndex].Height; } } // Word wrap code var sOriginal = e.Graphics.MeasureString(e.Value.ToString(), dataGridView1.Font); var sWrapped = e.Graphics.MeasureString(e.Value.ToString(), dataGridView1.Font, // Is is MeasureString that determines the height given the width, so // that it properly takes the actual wrapping into account dataGridView1.Columns[e.ColumnIndex].Width); if (sOriginal.Width != dataGridView1.Columns[e.ColumnIndex].Width) { using (Brush gridBrush = new SolidBrush(this.dataGridView1.GridColor), backColorBrush = new SolidBrush(e.CellStyle.BackColor), fontBrush = new SolidBrush(e.CellStyle.ForeColor)) { e.Graphics.FillRectangle(backColorBrush, e.CellBounds); // The DrawLine calls restore the missing borders: which borders // miss and how to paint them depends on border style settings e.Graphics.DrawLine(new Pen(gridBrush, 1), new Point(e.CellBounds.X - 1, e.CellBounds.Y + e.CellBounds.Height - 1), new Point(e.CellBounds.X + e.CellBounds.Width - 1, e.CellBounds.Y + e.CellBounds.Height - 1)); e.Graphics.DrawLine(new Pen(gridBrush, 1), new Point(e.CellBounds.X + e.CellBounds.Width - 1, e.CellBounds.Y - 1), new Point(e.CellBounds.X + e.CellBounds.Width - 1, e.CellBounds.Y + e.CellBounds.Height - 1)); //Updating the maximum cell height for wrapped text inside the row: // it will later be set to the row height to avoid the flickering // that would occur by setting the height multiple times. _rowMaxHeight = (Math.Ceiling(sWrapped.Height) > _rowMaxHeight) ? (int)Math.Ceiling(sWrapped.Height) : _rowMaxHeight; // The text is generated inside the row. e.Graphics.DrawString(e.Value.ToString(), dataGridView1.Font, fontBrush, e.CellBounds, StringFormat.GenericDefault); e.Handled = true; } } if (e.ColumnIndex == dataGridView1.ColumnCount - 1 && _rowMaxHeight > 0 && _rowMaxHeight != dataGridView1.Rows[e.RowIndex].Height) { // Setting the height only in the last cell, when the full row has been // painted, helps to avoid flickering when more than one row // needs the wrap. dataGridView1.Rows[e.RowIndex].Height = (_rowMaxHeight > _rowDefaultHeight) ? _rowMaxHeight : _rowDefaultHeight; } }
dataGridView1.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; dataGridView1.Columns[1].DefaultCellStyle.WrapMode = DataGridViewTriState.True; private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.Value == null) return; var s = e.Graphics.MeasureString(e.Value.ToString(), dataGridView1.Font); if (s.Width > dataGridView1.Columns[e.ColumnIndex].Width) { using (Brush gridBrush = new SolidBrush(this.dataGridView1.GridColor), backColorBrush = new SolidBrush(e.CellStyle.BackColor)) { using (Pen gridLinePen = new Pen(gridBrush)) { e.Graphics.FillRectangle(backColorBrush, e.CellBounds); e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right, e.CellBounds.Bottom - 1); e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1); e.Graphics.DrawString(e.Value.ToString(), dataGridView1.Font, Brushes.Black, e.CellBounds, StringFormat.GenericDefault); dataGridView1.Rows[e.RowIndex].Height = (int)(s.Height * Math.Ceiling(s.Width / dataGridView1.Columns[e.ColumnIndex].Width)); e.Handled = true; } } } }
The following code example illustrates how to use the row template to specify an initial row height and a minimum row height.
DataGridViewRow row = this.dataGridView1.RowTemplate; row.DefaultCellStyle.BackColor = Color.Bisque; row.Height = 35; row.MinimumHeight = 20;
DataGridView Overlap Cells => Column2 is a user control, not DataGridView custom cell. Sync with DataGridView Row.
Code here =>
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace DataGridViewRowHoldControl { public partial class Form1 : Form { DataTable table = new DataTable(); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { table.Columns.Add("Name", typeof(string)); table.Columns.Add("Control", typeof(Control)); DataRow row = table.NewRow(); row["Name"] = "A"; Button bt = new Button(); bt.Text = "A"; row["Control"] = bt; table.Rows.Add(row); row = table.NewRow(); row["Name"] = "B"; bt = new Button(); bt.Text = "B"; row["Control"] = bt; table.Rows.Add(row); dataGridView1.AutoGenerateColumns = false; dataGridView1.AllowUserToAddRows = false; BindingSource bs = new BindingSource(); bs.DataSource = table; dataGridView1.DataSource = bs; dataGridView1.Columns[0].DataPropertyName = "Name"; dataGridView1.AllowUserToResizeRows = true; //ShowButtons(table); ShowButtonsInit(table); Invalidate(); } private void ShowButtonsInit(DataTable table) { foreach (DataGridViewRow gRow in dataGridView1.Rows) { Size size = gRow.Cells[1].Size; Rectangle rect = dataGridView1.GetCellDisplayRectangle(1, gRow.Index, true); string name = gRow.Cells[0].Value.ToString(); DataRow dRow = table.Select("Name = '" + name + "'").First(); Button bt = dRow["Control"] as Button; bt.Location = new Point(rect.X, rect.Y); bt.Width = rect.Width; bt.Height = rect.Height; dataGridView1.Controls.Add(bt); } } private void ShowButtons(DataTable table) { foreach (DataGridViewRow gRow in dataGridView1.Rows) { Size size = gRow.Cells[1].Size; Rectangle rect = dataGridView1.GetCellDisplayRectangle(1, gRow.Index, true); string name = gRow.Cells[0].Value.ToString(); DataRow dRow = table.Select("Name = '" + name + "'").First(); Button bt = dRow["Control"] as Button; bt.Location = new Point(rect.X, rect.Y); bt.Width = rect.Width; bt.Height = rect.Height; //dataGridView1.Controls.Add(bt); } } private void button1_Click(object sender, EventArgs e) { ShowButtons(table); } private void dataGridView1_RowHeightChanged(object sender, DataGridViewRowEventArgs e) { ShowButtons(table); } } }
How to: Host Controls in Windows Forms DataGridView Cells
http://msdn.microsoft.com/en-us/library/7tas5c80.aspx
DataBinding Error
第一种方案:
绑定DataGridViewComboboxColumn 要早于绑定DataGridView。
第二种方案
在窗体加载函数(即构造函数)加上下面这句就好了: this.dataGridView.DataError += delegate(object sender, DataGridViewDataErrorEventArgs e) { };
或者添加DataError事件:
DataGridView.EditingControlShowing and DataGridView.CellValidating
Private Sub dataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing ' Here you control if combobox will be editable or not If e.CellStyle.Tag = "editable" Then Dim dataGridView1 As DataGridView = CType(sender, DataGridView) If (TypeOf (e.Control) Is ComboBox) Then Dim cb As ComboBox = CType(e.Control, ComboBox) If (Not cb Is Nothing) Then cb.DropDownStyle = ComboBoxStyle.DropDown If (MODE = CBO_MODE.EDITABLE_WITH_NOTIFYCURRENTCELLDIRTY) Then ' Added thanks to Ying Liu, Microsoft Support dataGridView1.NotifyCurrentCellDirty(True) End If End If End If End If End Sub Private Sub dataGridView1_CellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating Dim dataGridView1 As DataGridView = CType(sender, DataGridView) If (TypeOf dataGridView1.Columns(e.ColumnIndex) Is DataGridViewComboBoxColumn) Then Dim comboBoxColumn As DataGridViewComboBoxColumn = dataGridView1.Columns(e.ColumnIndex) If (Not comboBoxColumn.Items.Contains(e.FormattedValue)) Then If (ALLOW_ADDS) Then Beep() ' Audio confirmation that the item has been added (optional) comboBoxColumn.Items.Add(e.FormattedValue) Else ' How do we cancel? e.Cancel = True End If End If End If End Sub
DataGridView.DataSource = ?? => DataSet/DataTable or BindingSource.
http://www.cnblogs.com/icyJ/archive/2013/03/08/BindingSource.html
BindingSource and DataGridView
http://www.codeproject.com/Articles/24656/A-Detailed-Data-Binding-Tutorial