Windows Forms Data Controls and Data Binding FAQ
Windows Forms Data Controls and Data Binding FAQ
Microsoft Developer Network > Forums Home > Windows Forms Forums > Windows Forms Data Need Help with Forums? (FAQ)
Controls and Databinding > Windows Forms Data Controls and Databinding FAQ
Zhi-Xin Ye
This material should not be considered as a complete coverage of the frequently
5 asked questions, but it tries to capture the high-level features with some depth in the
Sign In Windows Forms Data Controls and Binding areas.
to Vote
All Replies
Zhi-Xin Ye
For example, assume you want to restrict users from setting focus on the second
column, then you have to derive from the DataGridView class and override the
SetCurrentCellAddressCore and SetSelectedCellCore to implement the logic you
want, the following sample demonstrates how to do this.
Code Block
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("c1");
dt.Columns.Add("c2");
dt.Columns.Add("c3");
for (int j = 0; j < 10; j++)
{
dt.Rows.Add("aaa" + j.ToString(), "bbb");
}
this.myDataGridView1.DataSource = dt;
this.myDataGridView1.ColumnToSkip = 1;
}
}
public class myDataGridView : DataGridView
{
private int columnToSkip = -1;
public int ColumnToSkip
{
get { return columnToSkip; }
set { columnToSkip = value; }
}
protected override bool SetCurrentCellAddressCore(int columnIndex, int rowIndex,
bool setAnchorCellAddress, bool validateCurrentCell, bool throughMouseClick)
{
if (columnIndex == this.columnToSkip && this.columnToSkip != -1)
{
if (this.columnToSkip == this.ColumnCount - 1)
{
return base.SetCurrentCellAddressCore(0, rowIndex + 1,
setAnchorCellAddress, validateCurrentCell, throughMouseClick);
}
else
{
if (this.ColumnCount != 0)
{
return base.SetCurrentCellAddressCore(columnIndex + 1, rowIndex,
setAnchorCellAddress, validateCurrentCell, throughMouseClick);
}
}
}
return base.SetCurrentCellAddressCore(columnIndex, rowIndex,
setAnchorCellAddress, validateCurrentCell, throughMouseClick);
}
protected override void SetSelectedCellCore(int columnIndex, int rowIndex, bool
selected)
{
if (columnIndex == this.columnToSkip)
{
if (this.columnToSkip == this.ColumnCount - 1)
{
base.SetSelectedCellCore(0, rowIndex + 1, selected);
}
else
{
if (this.ColumnCount != 0)
{
base.SetSelectedCellCore(columnIndex + 1, rowIndex, selected);
}
}
}
else
{
base.SetSelectedCellCore(columnIndex, rowIndex, selected);
}
}
}
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?
PostID=316283&SiteID=1
Zhi-Xin Ye
Code Block
private void Form1_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("c1");
dt.Columns.Add("c2");
for (int j = 0; j < 10; j++)
{
dt.Rows.Add("aaaaaaaaa", "bbbb");
}
this.dataGridView1.DataSource = dt;
for (int j = 0; j < 10; j++)
{
int height = TextRenderer.MeasureText(
this.dataGridView1[0, j].Value.ToString(),
this.dataGridView1.DefaultCellStyle.Font).Width;
this.dataGridView1.Rows[j].Height = height;
}
this.dataGridView1.CellPainting += new
DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting); ;
}
void dataGridView1_CellPainting(object sender,
DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex > -1 && e.Value != null)
{
e.Paint(e.CellBounds, DataGridViewPaintParts.All
& ~DataGridViewPaintParts.ContentForeground);
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
sf.FormatFlags = StringFormatFlags.DirectionVertical;
e.Graphics.DrawString(e.Value.ToString(), e.CellStyle.Font,
new SolidBrush(e.CellStyle.ForeColor), e.CellBounds, sf);
e.Handled = true;
}
}
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2351571&SiteID=1
Zhi-Xin Ye
To achieve this, we can derive from the DataGridView class and override its
OnColumnAdded method to change the default setting, something like this
Code Block
public
class mydgv : DataGridView
{
protected override void OnColumnAdded(DataGridViewColumnEventArgs e)
{
base.OnColumnAdded(e);
e.Column.SortMode = DataGridViewColumnSortMode.NotSortable;
}
}
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?
PostID=2302617&SiteID=1
Zhi-Xin Ye
Code Block
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1924281&SiteID=1
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2122903&SiteID=1
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1358083&SiteID=1
Zhi-Xin Ye
Zhi-Xin Ye
---------------------------------------------------------------
---------------------------------------------------------------
---------------------------------------------------------------
Zhi-Xin Ye
Code Block
0
Sign In
to Vote private void DgvColumnHeaderMerge_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;
}
}
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1378821&SiteID=1
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1442065&SiteID=1
0
Sign In As asked in this thread http://forums.microsoft.com/MSDN/ShowPost.aspx?
to Vote PostID=1425662&SiteID=1
the OP would like to make a Button to show up along with the TextBox. This can be
done by creating a UserControl to host the TextBox and Button, add it into the
controls collection of the DataGridView, initially make it invisible, then handle the
CellBeginEdit event to show the UserControl at the current cell. You also have to
handle the Scroll event to adjust the location of the UserControl in case the Scrollbars
shows, and handle the CellEndEdit event to change the cell value with the value got
from the UserControl. For a full sample please check the thread.
And there is another similar thread where the OP wants to display a Dropdown text
editor while editing in the cells.
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1506454&SiteID=1
The key point here is to handle the CellPainting event to custom draw the cell to get
the style you want, a sample code demonstrates how to do this:
Code Block
public class GroupByGrid : DataGridView
{
protected override void OnCellFormatting(
DataGridViewCellFormattingEventArgs args)
{
// Call home to base
base.OnCellFormatting(args);
// First row always displays
if (args.RowIndex == 0)
return;
if (IsRepeatedCellValue(args.RowIndex, args.ColumnIndex))
{
args.Value = string.Empty;
args.FormattingApplied = true;
}
}
private bool IsRepeatedCellValue(int rowIndex, int colIndex)
{
DataGridViewCell currCell =
Rows[rowIndex].Cells[colIndex];
DataGridViewCell prevCell =
Rows[rowIndex - 1].Cells[colIndex];
if ((currCell.Value == prevCell.Value) ||
0
Sign In To make the Enter key work as Tab key, we have to derive from the DataGridView control,
to Vote and there are two cases to think about. One is when the DataGridView is not in edit mode: in
this case, we can override the ProcessDataGridViewKey() method to change the navigation logic
as we want. The other case is when the DataGridView is in edit mode: in this case, the Enter key
is processed in the ProcessDialogKey() method, so we should override this method to write our
own logic. The following sample demonstrates how to do this.
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1864004&SiteID=1
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1437503&SiteID=1
10. How to restrict the input in the text column to be numeric only?
0
Sign In When the textbox cell is in edit mode, the EditingControl is shown in the cell, we can
to Vote restrict the input by handling the TextBox.KeyPress event to filter the keyboard input
through the char.IsDigit() method. The following sample demonstrates how to do this.
Code Block
public partial class DgvNumberOnlyColumn : Form
{
public DgvNumberOnlyColumn()
{
InitializeComponent();
}
private void DgvNumberOnlyColumn_Load(object sender, EventArgs e)
{
this.dataGridView1.Columns.Add("col1", "col1");
this.dataGridView1.Columns.Add("col2", "col2");
this.dataGridView1.Rows.Add();
this.dataGridView1.EditingControlShowing += new
DataGridViewEditingControlShowingEventHandler(
dataGridView1_EditingControlShowing);
}
void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
if (this.dataGridView1.CurrentCell.ColumnIndex == 0)
{
if (e.Control is TextBox)
{
TextBox tb = e.Control as TextBox;
tb.KeyPress -= new KeyPressEventHandler(tb_KeyPress);
tb.KeyPress += new KeyPressEventHandler(tb_KeyPress);
}
}
}
void tb_KeyPress(object sender, KeyPressEventArgs e)
{
if (!(char.IsDigit(e.KeyChar)))
{
Keys key = (Keys)e.KeyChar;
if (!(key == Keys.Back || key == Keys.Delete))
{
e.Handled = true;
}
}
}
}
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1757999&SiteID=1
11. How to make the '\t' character work in the DataGridViewCell when
displaying?
0
Sign In
to Vote When the DataGridView paints the cell value, the '\t' character is ignored by default. To
make the '\t' char work, we can handle the CellPainting event to draw the text by
ourselves.
Code Block
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1898048&SiteID=1
12. How to make the Enter key and Tab key work in DataGridViewTextBoxCell
when in edit mode?
0
Sign In To make the Enter key and Tab key work in the cell while editing, you have to derive
to Vote from the DataGridView control, override the ProcessDataGridViewKey method to filter
the Tab and Enter key, something like this:
Code Block
To make the Tab key work in edit mode, you have to set the AcceptsTab property to
true for the TextBox as well.
Code Block
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1898048&SiteID=1
13. How to make the DataGridView show gridlines in all display areas?
Code Block
public class GridLineDataGridView : DataGridView
{
public GridLineDataGridView()
{
this.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
int rowHeight = this.RowTemplate.Height;
int h = this.ColumnHeadersHeight + rowHeight * this.RowCount;
int imgWidth = this.Width - 2;
Rectangle rFrame = new Rectangle(0, 0, imgWidth, rowHeight);
Rectangle rFill = new Rectangle(1, 1, imgWidth - 2, rowHeight);
Rectangle rowHeader = new Rectangle(2, 2, this.RowHeadersWidth - 3,
rowHeight);
Pen pen = new Pen(this.GridColor, 1);
Related threads:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2241055&SiteID=1
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1947368&SiteID=1
While you can navigate to a read-only cell, and you can set a read-only cell to be
the current cell, the content cannot be modified by the user. Note that the ReadOnly
property does not keep the cell from being modified programmatically. Also note that
ReadOnly does not affect whether the user can delete rows.
Code Block
{
public DataGridViewDisableButtonColumn()
{
this.CellTemplate = new DataGridViewDisableButtonCell();
}
}
public class DataGridViewDisableButtonCell : DataGridViewButtonCell
{
private bool enabledValue;
public bool Enabled
{
get
{
return enabledValue;
}
set
{
enabledValue = value;
}
}
// Override the Clone method so that the Enabled property is copied.
public override object Clone()
{
DataGridViewDisableButtonCell cell =
(DataGridViewDisableButtonCell)base.Clone();
cell.Enabled = this.Enabled;
return cell;
}
// By default, enable the button cell.
public DataGridViewDisableButtonCell()
{
this.enabledValue = true;
}
protected override void Paint(Graphics graphics,
Rectangle clipBounds, Rectangle cellBounds, int rowIndex,
DataGridViewElementStates elementState, object value,
object formattedValue, string errorText,
DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle,
DataGridViewPaintParts paintParts)
{
// The button cell is disabled, so paint the border,
// background, and disabled button for the cell.
if (!this.enabledValue)
{
// Draw the cell background, if specified.
if ((paintParts & DataGridViewPaintParts.Background) ==
DataGridViewPaintParts.Background)
{
SolidBrush cellBackground =
new SolidBrush(cellStyle.BackColor);
graphics.FillRectangle(cellBackground, cellBounds);
cellBackground.Dispose();
}
// Draw the cell borders, if specified.
if ((paintParts & DataGridViewPaintParts.Border) ==
DataGridViewPaintParts.Border)
{
PaintBorder(graphics, clipBounds, cellBounds, cellStyle,
advancedBorderStyle);
}
// Calculate the area in which to draw the button.
Rectangle buttonArea = cellBounds;
Rectangle buttonAdjustment =
this.BorderWidths(advancedBorderStyle);
buttonArea.X += buttonAdjustment.X;
buttonArea.Y += buttonAdjustment.Y;
buttonArea.Height -= buttonAdjustment.Height;
buttonArea.Width -= buttonAdjustment.Width;
// Draw the disabled button.
0
Sign In The DataGridView control only supports displaying an actual control when a cell is
to Vote in edit mode. The DataGridView control is not designed to display multiple controls or
repeat a set of controls per row. The DataGridView control draws a representation of
the control when the cell is not being edited. This representation can be a detailed as
you want. For example, the DataGridViewButtonCell draws a button regardless of the
cell being in edit or not.
However, you can add controls through DataGridView.Controls.Add() method, and
set their location and size to make them hosted in the cells, but showing controls in all
cells regardless of editing make no sense.
Code Block
0
Sign In The DataGridView control does not have any built-in support for showing an icon
to Vote and text in the same cell. Through the different painting customization events, such as
the CellPainting event, you can easily display an icon next to the text in the cell.
The following example extends the DataGridViewTextColumn and cell to paint an
image next to the text. The sample uses the DataGridViewCellStyle.Padding property to
adjust the text location and overrides the Paint method to paint an icon. This sample
can be simplified by handling the CellPainting event and performing similar code.
Code Block
Code Block
0
Sign In public class TextAndImageCell : DataGridViewTextBoxCell
to Vote
{
private Image imageValue;
private Size imageSize;
public override object Clone()
{
TextAndImageCell c = base.Clone() as TextAndImageCell;
c.imageValue = this.imageValue;
c.imageSize = this.imageSize;
return c;
}
public Image Image
{
get
{
if (this.OwningColumn == null ||
this.OwningTextAndImageColumn == null)
{
return imageValue;
}
else if (this.imageValue != null)
{
return this.imageValue;
}
else
{
return this.OwningTextAndImageColumn.Image;
}
}
set
{
if (this.imageValue != value)
{
this.imageValue = value;
this.imageSize = value.Size;
0 Sometimes you will want to display only some of the columns that are available in
Sign In a DataGridView. For example, you might want to show an employee salary column to
to Vote users with management credentials while hiding it from other users.
In the DataGridView control, the column's Visible property determines whether the
column is displayed.
In the DataGridView control, the SortMode property value of a column determines its
sorting behavior.
When the DataGridView is databound the datasource can be sorted on multiple
columns and the DataGridView will respect that sorting, but the only the first sorted
column will display the sort glyph. In addition, the SortedColumn property will only
return the first sorted column.
Some datasources have built in support for sorting on multiple columns. If your
datasource implements IBindingListView and provides support for the Sort property,
then using it will provide support for multi-column sorting. To indicate in the grid that
multiple columns are sorted on, manually set a column's SortGlyphDirection to
properly indicate that the column is sorted.
The following example uses a DataTable and sets the default view's Sort property
to sort on the second and third columns. The example also demonstrates setting the
column's SortGlyphDirection. The example assumes that you have a DataGridView and
a BindingSource component on your form:
Code Block
col1.HeaderCell.SortGlyphDirection = SortOrder.Ascending;
DataGridViewTextBoxColumn col2 = new
DataGridViewTextBoxColumn();
col2.DataPropertyName = "C3";
dataGridView1.Columns.Add(col2);
col2.SortMode = DataGridViewColumnSortMode.Programmatic;
col2.HeaderCell.SortGlyphDirection = SortOrder.Ascending;
Code Block
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
class Form1 : Form
{
private DataGridView dataGridView1 = new DataGridView();
// Establish the main entry point for the application.
[STAThreadAttribute()]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
public Form1()
{
// Initialize the form.
// This code can be replaced with designer generated code.
dataGridView1.AllowUserToAddRows = false;
dataGridView1.Dock = DockStyle.Fill;
dataGridView1.SortCompare += new DataGridViewSortCompareEventHandler(
this.dataGridView1_SortCompare);
Controls.Add(this.dataGridView1);
this.Text = "DataGridView.SortCompare demo";
PopulateDataGridView();
}
// Replace this with your own population code.
public void PopulateDataGridView()
{
// Add columns to the DataGridView.
dataGridView1.ColumnCount = 3;
Code Block
using System;
using System.Drawing;
using System.Windows.Forms;
class Form1 : Form
{
private DataGridView DataGridView1 = new DataGridView();
private FlowLayoutPanel FlowLayoutPanel1 = new FlowLayoutPanel();
private Button Button1 = new Button();
private RadioButton RadioButton1 = new RadioButton();
private RadioButton RadioButton2 = new RadioButton();
// Establish the main entry point for the application.
[STAThreadAttribute()]
public static void Main()
{
Application.Run(new Form1());
}
public Form1()
{
// Initialize the form.
// This code can be replaced with designer generated code.
AutoSize = true;
Text = "DataGridView IComparer sort demo";
FlowLayoutPanel1.FlowDirection = FlowDirection.TopDown;
FlowLayoutPanel1.Location = new System.Drawing.Point(304, 0);
FlowLayoutPanel1.AutoSize = true;
FlowLayoutPanel1.Controls.Add(RadioButton1);
FlowLayoutPanel1.Controls.Add(RadioButton2);
FlowLayoutPanel1.Controls.Add(Button1);
Button1.Text = "Sort";
RadioButton1.Text = "Ascending";
RadioButton2.Text = "Descending";
RadioButton1.Checked = true;
Controls.Add(FlowLayoutPanel1);
Controls.Add(DataGridView1);
}
protected override void OnLoad(EventArgs e)
{
PopulateDataGridView();
Button1.Click += new EventHandler(Button1_Click);
base.OnLoad(e);
}
// Replace this with your own code to populate the DataGridView.
private void PopulateDataGridView()
{
DataGridView1.Size = new Size(300, 300);
// Add columns to the DataGridView.
DataGridView1.ColumnCount = 2;
// Set the properties of the DataGridView columns.
DataGridView1.Columns[0].Name = "First";
DataGridView1.Columns[1].Name = "Last";
DataGridView1.Columns["First"].HeaderText = "First Name";
DataGridView1.Columns["Last"].HeaderText = "Last Name";
DataGridView1.Columns["First"].SortMode =
DataGridViewColumnSortMode.Programmatic;
DataGridView1.Columns["Last"].SortMode =
DataGridViewColumnSortMode.Programmatic;
// Add rows of data to the DataGridView.
DataGridView1.Rows.Add(new string[] { "Peter", "Parker" });
DataGridView1.Rows.Add(new string[] { "James", "Jameson" });
DataGridView1.Rows.Add(new string[] { "May", "Parker" });
DataGridView1.Rows.Add(new string[] { "Mary", "Watson" });
DataGridView1.Rows.Add(new string[] { "Eddie", "Brock" });
}
private void Button1_Click(object sender, EventArgs e)
{
if (RadioButton1.Checked == true)
{
DataGridView1.Sort(new RowComparer(SortOrder.Ascending));
}
else if (RadioButton2.Checked == true)
{
DataGridView1.Sort(new RowComparer(SortOrder.Descending));
}
}
private class RowComparer : System.Collections.IComparer
{
Code Block
private Rectangle dragBoxFromMouseDown;
private int rowIndexFromMouseDown;
private int rowIndexOfItemUnderMouseToDrop;
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
// If the mouse moves outside the rectangle, start the drag.
if (dragBoxFromMouseDown != Rectangle.Empty &&
!dragBoxFromMouseDown.Contains(e.X, e.Y))
{
// Proceed with the drag and drop, passing in the list
item.
23. How do I make the last column wide enough to occupy all the remaining
client area of the grid?
0
Sign In
to Vote By setting the AutoSizeMode for the last column to Fill the column will size itself to
fill in the remaining client area of the grid. Optionally you can set the last column's
MinimumWidth if you want to keep the column from sizing too small.
Code Block
this.dataGridView1.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
25. How do I make the image column not show any images?
0
Sign In By default the image column and cell convert null values to the standard "X" image .
to Vote You can make no image show up by changing the column’s NullValue property to null.
The following code example sets the NullValue for an image column:
Code Block
DataGridViewCellValidatingEventArgs e)
{
if (e.ColumnIndex == comboBoxColumn.DisplayIndex)
{
if (!this.comboBoxColumn.Items.Contains(e.FormattedValue))
{
this.comboBoxColumn.Items.Add(e.FormattedValue);
}
}
}
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
if (this.dataGridView1.CurrentCellAddress.X ==
comboBoxColumn.DisplayIndex)
{
ComboBox cb = e.Control as ComboBox;
if (cb != null)
{
cb.DropDownStyle = ComboBoxStyle.DropDown;
}
}
}
27. How do I have a combo box column display a sub set of data based upon the
value of a different combo box column?
0
Sign In Sometimes data that you want to display in the DataGridView has a relationship
to Vote between two tables such as a category and subcategory. You want to let the user
select the category and then choose between a subcategory based upon the category.
This is possible with the DataGridView by using two combo box columns. To enable
this, two versions of the filtered list (subcategory) needs to be created. One list has no
filter applied while the other one will be filtered only when the user is editing a
subcategory cell. Two lists are required due to the requirement that a combo box cells
value must be in the items collection or else a DataError event is raised. In this case,
since all combo box cells in the column use the same datasource if you filter the
datasource for one row then a combo box cell in another row might not have its value
visible in the datasource, thus causing a DataError event.
The below example uses the Northwind database to display related data from the
Territory and Region tables (a territory is in a specific region.) Using the category and
subcategory concept, the Region is the category and the Territory is the subcategory.
Code Block
{
// Set the combobox cell datasource to the filtered BindingSource
DataGridViewComboBoxCell dgcb =
(DataGridViewComboBoxCell)dataGridView1
[e.ColumnIndex, e.RowIndex];
dgcb.DataSource = filteredTerritoriesBS;
// Filter the BindingSource based upon the region selected
this.filteredTerritoriesBS.Filter = "RegionID = " +
this.dataGridView1[e.ColumnIndex - 1, e.RowIndex].Value.ToString();
}
}
private void dataGridView1_CellEndEdit(object sender,
DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == this.territoryComboBoxColumn.Index)
{
// Reset combobox cell to the unfiltered BindingSource
DataGridViewComboBoxCell dgcb =
(DataGridViewComboBoxCell)dataGridView1
[e.ColumnIndex, e.RowIndex];
dgcb.DataSource = territoriesBindingSource; //unfiltered
this.filteredTerritoriesBS.RemoveFilter();
}
}
28. How do I show the error icon when the user is editing the cell?
0 Sometimes when using the error text and icon feature you want an immediate
Sign In feedback to the user that something that they typed into a cell is incorrect. By default
to Vote when setting the ErrorText property the error icon will not appear if the cell is in edit
mode such as a text box or combo box cell.
The below sample demonstrates how you can set a cell's padding in the CellValidating
event to provide spacing for the error icon. Since padding by default affects the
location of the error icon the sample uses the CellPainting to move the position of the
icon for painting. Lastly, the sample uses the tooltip control to display a custom tooltip
when the mouse is over the cell to indicate what the problem is. This sample could
also be written as a custom cell that overrides GetErrorIconBounds method to provide
a location for the error icon that was independent of the padding.
Code Block
private ToolTip errorTooltip;
private Point cellInError = new Point(-2, -2);
public Form1()
{
InitializeComponent();
dataGridView1.ColumnCount = 3;
dataGridView1.RowCount = 10;
}
private void dataGridView1_CellValidating(object sender,
DataGridViewCellValidatingEventArgs e)
{
if (dataGridView1.IsCurrentCellDirty)
{
if (e.FormattedValue.ToString() == "BAD")
{
DataGridViewCell cell = dataGridView1[e.ColumnIndex,
e.RowIndex];
cell.ErrorText = "Invalid data entered in cell";
// increase padding for icon. This moves the editing control
if (cell.Tag == null)
{
cell.Tag = cell.Style.Padding;
cell.Style.Padding = new Padding(0, 0, 18, 0);
cellInError = new Point(e.ColumnIndex, e.RowIndex);
}
if (errorTooltip == null)
{
errorTooltip = new ToolTip();
errorTooltip.InitialDelay = 0;
errorTooltip.ReshowDelay = 0;
errorTooltip.Active = false;
}
e.Cancel = true;
}
}
}
private void dataGridView1_CellPainting(object sender,
DataGridViewCellPaintingEventArgs e)
{
if (dataGridView1.IsCurrentCellDirty &&
!String.IsNullOrEmpty(e.ErrorText))
{
// paint everything except error icon
e.Paint(e.ClipBounds, DataGridViewPaintParts.All &
~(DataGridViewPaintParts.ErrorIcon));
// now move error icon over to fill in the padding space
GraphicsContainer container = e.Graphics.BeginContainer();
e.Graphics.TranslateTransform(18, 0);
e.Paint(this.ClientRectangle, DataGridViewPaintParts.ErrorIcon);
e.Graphics.EndContainer(container);
e.Handled = true;
}
}
private void dataGridView1_CellEndEdit(object sender,
DataGridViewCellEventArgs e)
{
if (dataGridView1[e.ColumnIndex, e.RowIndex].ErrorText !=
String.Empty)
{
DataGridViewCell cell = dataGridView1[e.ColumnIndex, e.RowIndex];
cell.ErrorText = String.Empty;
cellInError = new Point(-2,-2);
// restore padding for cell. This moves the editing control
cell.Style.Padding = (Padding)cell.Tag;
// hide and dispose tooltip
if (errorTooltip != null)
{
errorTooltip.Hide(dataGridView1);
errorTooltip.Dispose();
errorTooltip = null;
}
}
}
// show and hide the tooltip for error
private void dataGridView1_CellMouseMove(object sender,
DataGridViewCellMouseEventArgs e)
{
if (cellInError.X == e.ColumnIndex &&
cellInError.Y == e.RowIndex)
{
DataGridViewCell cell = dataGridView1[e.ColumnIndex, e.RowIndex];
if (cell.ErrorText != String.Empty)
{
if (!errorTooltip.Active)
{
errorTooltip.Show(cell.ErrorText, dataGridView1, 1000);
}
errorTooltip.Active = true;
}
}
}
private void dataGridView1_CellMouseLeave(object sender,
DataGridViewCellEventArgs e)
{
if (cellInError.X == e.ColumnIndex &&
cellInError.Y == e.RowIndex)
{
if (errorTooltip.Active)
{
errorTooltip.Hide(dataGridView1);
errorTooltip.Active = false;
}
}
}
0 The data you display in the DataGridView control will normally come from a data
Sign In source of some kind, but you might want to display a column of data that does not
to Vote come from the data source. This kind of column is called an unbound column.
Unbound columns can take many forms. As discussed in the data section above, you
can use virtual mode to display additional data along with bound data.
The following code example demonstrates how to create an unbound column of check
box cells to enable the user to select database records to process. The grid is put into
virtual mode and responds to the necessary events. The selected records are kept by
ID in a dictionary to allow the user to sort the content but not lose the checked rows.
Code Block
}
private void dataGridView1_CellValueNeeded(object sender,
DataGridViewCellValueEventArgs e)
{
// Handle the notification that the value for a cell in the virtual
column
// is needed. Get the value from the dictionary if the key exists.
if (e.ColumnIndex == 0)
{
int orderID =
(int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;
if (checkState.ContainsKey(orderID))
{
e.Value = checkState[orderID];
}
else
e.Value = false;
}
}
private void dataGridView1_CellValuePushed(object sender,
DataGridViewCellValueEventArgs e)
{
// Handle the notification that the value for a cell in the virtual
column
// needs to be pushed back to the dictionary.
if (e.ColumnIndex == 0)
{
// Get the orderID from the OrderID column.
int orderID =
(int)dataGridView1.Rows[e.RowIndex].Cells["OrderID"].Value;
// Add or update the checked value to the dictionary
depending on if the
// key (orderID) already exists.
if (!checkState.ContainsKey(orderID))
{
checkState.Add(orderID, (bool)e.Value);
}
else
checkState[orderID] = (bool)e.Value;
}
}
0 One of the most common scenarios for using the DataGridView control is the
Sign In master/detail form, in which a parent/child relationship between two database tables is
to Vote displayed. Selecting rows in the master table causes the detail table to update with
the corresponding child data.
Code Block
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
public class Form1 : System.Windows.Forms.Form
{
private DataGridView masterDataGridView = new DataGridView();
private BindingSource masterBindingSource = new BindingSource();
private DataGridView detailsDataGridView = new DataGridView();
private BindingSource detailsBindingSource = new BindingSource();
[STAThreadAttribute()]
public static void Main()
{
Application.Run(new Form1());
}
// Initializes the form.
public Form1()
{
masterDataGridView.Dock = DockStyle.Fill;
detailsDataGridView.Dock = DockStyle.Fill;
SplitContainer splitContainer1 = new SplitContainer();
splitContainer1.Dock = DockStyle.Fill;
splitContainer1.Orientation = Orientation.Horizontal;
splitContainer1.Panel1.Controls.Add(masterDataGridView);
splitContainer1.Panel2.Controls.Add(detailsDataGridView);
this.Controls.Add(splitContainer1);
this.Load += new System.EventHandler(Form1_Load);
this.Text = "DataGridView master/detail demo";
}
private void Form1_Load(object sender, System.EventArgs e)
{
// Bind the DataGridView controls to the BindingSource
// components and load the data from the database.
masterDataGridView.DataSource = masterBindingSource;
detailsDataGridView.DataSource = detailsBindingSource;
GetData();
// Resize the master DataGridView columns to fit the newly loaded data.
masterDataGridView.AutoResizeColumns();
// Configure the details DataGridView so that its columns automatically
// adjust their widths when the data changes.
detailsDataGridView.AutoSizeColumnsMode =
DataGridViewAutoSizeColumnsMode.AllCells;
}
private void GetData()
{
try
{
// Specify a connection string. Replace the given value with a
// valid connection string for a Northwind SQL Server sample
// database accessible to your system.
0 The DataGridView does not provide any support for showing master-details data in
Sign In the same DataGridView. The previously shipped Windows Forms DataGrid control can
to Vote be a solution if this is something that you need.
to Vote property by right-clicking on the DataGridView and choosing the Edit Columns option.
Next select the column that you want to disable sorting for and set the SortMode
property to NotSortable.
Code Block
this.Validate();
this.customersBindingSource.EndEdit();
this.customersTableAdapter.Update(this.northwindDataSet.Customers);
35. How do I display a confirmation dialog when the user tries to delete a row?
0 When the user selects a row in the DataGridView and hits the delete key, the
Sign In UserDeletingRow event fires. You can prompt the user if they want to continue
to Vote deleting the row. It is recommended that you only do this if the row being deleted is
not the new row. Add the following code to the UserDeletingRow event handler to
perform this:
Code Block
if (!e.Row.IsNewRow)
{
DialogResult response = MessageBox.Show("Are you sure?",
"Delete row?",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2);
if (response == DialogResult.No)
e.Cancel = true;
}
© 2010 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement | Contact Us | Manage Your Profile