I can't think of an efficient way to do this, but here are some ideas that may work with small data sets.
Keep up with the values yourself
1) Don't define the column as an AutoIncrement column):
DataColumn itemNumber = new DataColumn();
itemNumber.ColumnName = "ItemNumber";
//itemNumber.AutoIncrement = true;
//itemNumber.AutoIncrementSeed = 1;
//itemNumber.AutoIncrementStep = 1;
2) Handle the DataGridView.RowsAdded
and DataGridView.RowsRemoved
events and "reset" the values:
private void dgvView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
if (dgvView.Columns.Contains("ItemNumber"))
{
foreach (DataGridViewRow r in dgvView.Rows)
{
r.Cells["ItemNumber"].Value = r.Index + 1;
}
}
}
private void dgvView_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
{
if (dgvView.Columns.Contains("ItemNumber"))
{
foreach (DataGridViewRow r in dgvView.Rows)
{
r.Cells["ItemNumber"].Value = r.Index + 1;
}
}
}
Regenerate the values by rebuilding the DataTable
and rebinding to it
1) Define the helper method below:
private DataTable ResetAutoIncrementColumn(DataTable dt, string autoIncrementColumnName)
{
DataTable result = new DataTable();
DataColumn itemNumber = new DataColumn(autoIncrementColumnName);
itemNumber.AutoIncrement = true;
itemNumber.AutoIncrementSeed = 1;
itemNumber.AutoIncrementStep = 1;
result.Columns.Add(itemNumber);
dt.Columns.Remove(autoIncrementColumnName);
result.Merge(dt, true);
return result;
}
2) Call it at the appropriate time (e.g. after a series of deletes as in the original question):
dt = ResetAutoIncrementColumn(dt, "ItemNumber");
dt.Columns["ItemNumber"].SetOrdinal(0);
dgvView.DataSource = dt;
dgvView.Columns["ItemNumber"].DisplayIndex = 0;
If you are just looking for a visual row number
Also, if you are just looking to have a visual row number on the DataGridView
(and you don't care about the value being present in the underlying DataTable
), you can handle the DataGridView.RowPostPaint
event as follows (pulled from https://stackoverflow.com/a/12840794/3085273):
private void dgGrid_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
var grid = sender as DataGridView;
var rowIdx = (e.RowIndex + 1).ToString();
var centerFormat = new StringFormat()
{
// right alignment might actually make more sense for numbers
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
var headerBounds = new Rectangle(e.RowBounds.Left, e.RowBounds.Top, grid.RowHeadersWidth, e.RowBounds.Height);
e.Graphics.DrawString(rowIdx, this.Font, SystemBrushes.ControlText, headerBounds, centerFormat);
}