[C#] DataGridView 자동 행 번호 생성하는 방법(예제)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CjControls
{
public partial class CjDataGridView : DataGridView
{
#region Attributes
/// <summary>
/// 행번호를 자동으로 생성할지 여부 (default=false). RowHeadersVisible=true일 때 사용 가능함
/// </summary>
private bool m_bAutoRowIndex = false;
[Browsable(true)]
[Category("CjDataGridView")]
[Description("행번호를 자동으로 생성할지 여부. RowHeadersVisible=true일 때 사용 가능함")]
[DefaultValue(false)]
public bool IsAutoRowIndex
{
get { return m_bAutoRowIndex; }
set
{
this.RowHeadersVisible = value;
if (m_bAutoRowIndex != value)
{
m_bAutoRowIndex = value;
this.Update();
}
}
}
/// <summary>
/// 수평 스크롤바를 제거하도록 마지막 컬럼의 폭을 자동 조정할지의 여부 (default=true)
/// </summary>
private bool m_bAutoRemoveHScrollbar = true;
[Browsable(true)]
[Category("CjDataGridView")]
[Description("수평 스크롤바를 제거하도록 마지막 컬럼의 폭을 자동 조정할지의 여부")]
[DefaultValue(true)]
public bool IsAutoRemoveHScrollbar
{
get { return m_bAutoRemoveHScrollbar; }
set
{
m_bAutoRemoveHScrollbar = value;
}
}
/// <summary>
/// 자동으로 생성되는 행의 시작번호 (default=1)
/// </summary>
private int m_nAutoIndexStartNo = 1;
[Browsable(true)]
[Category("CjDataGridView")]
[Description("자동으로 생성되는 행의 시작번호")]
[DefaultValue(1)]
public int AutoIndexStartNo
{
get { return m_nAutoIndexStartNo; }
set
{
if (value < 0)
return;
m_nAutoIndexStartNo = value;
}
}
[Browsable(false)]
[Category("CjDataGridView")]
[Description("바인딩 데이터테이블")]
[DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public System.Data.DataTable BindingToTable
{
get
{
if (this.Columns.Count > 0)
{
System.Data.DataTable dt = new System.Data.DataTable();
var cols = from DataGridViewColumn v in this.Columns orderby v.Index select v;
foreach (DataGridViewColumn v in cols)
{
System.Data.DataColumn c = dt.Columns.Add(v.Name, v.ValueType);
c.Caption = v.HeaderText;
}
var rows = from DataGridViewRow v in this.Rows orderby v.Index select v;
foreach (DataGridViewRow v in rows)
{
object[] dr = new object[this.Columns.Count];
for (int c = 0; c < this.Columns.Count; ++c)
{
dr[c] = this.Rows[v.Index].Cells[c].Value;
}
dt.Rows.Add(dr);
}
return dt;
}
else
return null;
}
}
[Browsable(false)]
[Category("CjDataGridView")]
[Description("바인딩 데이터셋")]
[DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public System.Data.DataSet BindingToSet
{
get
{
if (this.Columns.Count > 0)
{
System.Data.DataSet ds = new System.Data.DataSet();
System.Data.DataTable dt = new System.Data.DataTable();
var cols = from DataGridViewColumn v in this.Columns orderby v.Index select v;
if (cols.Count() > 0)
{
foreach (DataGridViewColumn v in cols)
{
dt.Columns.Add(v.Name, v.ValueType);
}
}
var rows = from DataGridViewRow v in this.Rows orderby v.Index select v;
if (rows.Count() > 0)
{
foreach (DataGridViewRow v in rows)
{
object[] dr = new object[this.Columns.Count];
for (int c = 0; c < this.Columns.Count; ++c)
dr[c] = this.Rows[v.Index].Cells[c].Value;
dt.Rows.Add(dr);
}
}
ds.Tables.Add(dt);
return ds;
}
else
return null;
}
}
[Browsable(false)]
[Category("CjDataGridView")]
[Description("바인딩 리스트")]
[DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public BindingList<object> BindingToList
{
get
{
if (this.Columns.Count > 0 && this.Rows.Count > 0)
{
BindingList<object> list = new BindingList<object>();
object[,] objects = new object[this.Rows.Count, this.Columns.Count];
var cols = (from DataGridViewColumn v in this.Columns orderby v.Index select v).ToList();
if (cols.Count() > 0)
{
for (int c = 0; c < this.Columns.Count; ++c)
{
objects[0, c] = cols[c].Name;
}
}
var rows = (from DataGridViewRow v in this.Rows orderby v.Index select v).ToList();
if (rows.Count() > 0)
{
for (int r = 0; r < this.Rows.Count; ++r)
{
for (int c = 0; c < this.Columns.Count; ++c)
objects[r, c] = rows[r].Cells[c].Value;
}
}
list.Add(objects);
return list;
}
else
return null;
}
}
/// <summary>
/// 칼럼별 수평 출력 방식
/// </summary>
private DataGridViewContentAlignment[] m_lstColumnAligns = null;
[Browsable(true)]
[Category("CjDataGridView")]
[Description("칼럼별 수평 출력 방식")]
[DefaultValue(null)]
public DataGridViewContentAlignment[] ColumnAligns
{
get { return m_lstColumnAligns; }
set
{
if (this.m_lstColumnAligns != null)
{
m_lstColumnAligns.Initialize();
m_lstColumnAligns = null;
}
m_lstColumnAligns = value;
Refresh();
}
}
#endregion
#region 생성자
/// <summary>
/// 생성자
/// </summary>
public CjDataGridView()
: base()
{
InitializeComponent();
}
#if _REMOVE_GGAMBBAK
/// <summary>
/// 화면에 표시될 때 생기는 화면 깜빡임 방지
/// </summary>
protected override CreateParams CreateParams
{
get
{
var cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
#endif
#endregion
#region 컨트롤 이벤트 처리
/// <summary>
/// 마우스 다운했을 때
/// </summary>
/// <param name="e"></param>
protected override void OnMouseDown(MouseEventArgs e)
{
//Debug.WriteLine($"OnMouseDown started: {e.Button}, {e.Location}");
base.OnMouseDown(e);
}
/// <summary>
/// 사용자가 행을 추가한 후
/// </summary>
/// <param name="e"></param>
protected override void OnUserAddedRow(DataGridViewRowEventArgs e)
{
try
{
base.OnUserAddedRow(e);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
/// <summary>
/// 모든 셀 그리기가 발생한 후 행 수준 그리기를 수행하기 위해 발생하는 이벤트
/// </summary>
/// <param name="e"></param>
protected override void OnRowPostPaint(DataGridViewRowPostPaintEventArgs e)
{
try
{
if (IsAutoRowIndex)
DGV_AutoRowIndex(this, e);
else
base.OnRowPostPaint(e);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
finally
{
if (IsAutoRemoveHScrollbar)
AutoRemoveHScrollbar();
}
}
#endregion
#region 외부함수
/// <summary>
/// 컨트롤 초기화
/// </summary>
/// <param name="bindingData">로딩할 데이터 데이블</param>
public void InitControl(DataTable bindingData = null, List<DataGridViewContentAlignment> lstColumnAligns = null)
{
Cursor.Current = Cursors.WaitCursor;
try
{
this.AllowUserToAddRows = false;
this.AllowUserToDeleteRows = false;
this.AllowUserToOrderColumns = false;
this.AllowUserToResizeColumns = true;
this.AllowUserToResizeRows = false;
this.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.ReadOnly = true;
this.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
this.RowHeadersVisible = IsAutoRowIndex;
this.Columns.Clear();
this.DataSource = null;
if (lstColumnAligns != null)
{
if (this.m_lstColumnAligns != null)
{
m_lstColumnAligns.Initialize();
m_lstColumnAligns = null;
}
this.m_lstColumnAligns = lstColumnAligns.ToArray();
}
if (bindingData != null && bindingData.Columns.Count > 0)
{
int wi = (this.Width - (IsAutoRowIndex ? this.RowHeadersWidth : 0)) / bindingData.Columns.Count;
for (int i = 0; i < bindingData.Columns.Count; i++)
{
DataColumn col = bindingData.Columns[i];
int c = this.Columns.Add(col.ColumnName, col.Caption);
this.Columns[c].DataPropertyName = col.ColumnName;
this.Columns[c].Width = wi;
if (m_lstColumnAligns == null)
m_lstColumnAligns = new DataGridViewContentAlignment[bindingData.Columns.Count];
if (m_lstColumnAligns.Count() <= c)
m_lstColumnAligns.Append(this.Columns[c].DefaultCellStyle.Alignment);
else
this.Columns[c].DefaultCellStyle.Alignment = m_lstColumnAligns[c];
}
foreach (DataRow row in bindingData.Rows)
{
int r = this.Rows.Add();
for (int c = 0; c < bindingData.Columns.Count; c++)
{
this.Rows[r].Cells[c].Value = row[c] as string;
}
}
this.DataSource = bindingData;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
finally
{
Cursor.Current = Cursors.Default;
}
}
/// <summary>
/// 수평 스크롤바를 제거하도록 마지막 컬럼의 폭을 자동 조정한다.
/// </summary>
public void AutoRemoveHScrollbar()
{
try
{
int lastColumnWidth = (this.Width - (IsAutoRowIndex ? this.RowHeadersWidth : 0))
- (from DataGridViewColumn v in this.Columns
where v.Index != (this.Columns.Count - 1)
select v.Width).Sum();
if (this.Width < this.RowTemplate.Height * this.Rows.Count)
{
this.Columns[this.Columns.Count - 1].Width = lastColumnWidth
- SystemInformation.VerticalScrollBarWidth
- SystemInformation.FrameBorderSize.Width;
this.Update();
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
/// <summary>
/// DataGridView 의 RowHeader 에 일련번호 자동생성
/// </summary>
/// <param name="sender">DataGridView 컨트롤</param>
/// <param name="e">이벤트정보</param>
/// <param name="startno">시작번호</param>
/// <remarks>DataGridView의 RowPostPaint 이벤트에 사용함</remarks>
public void DGV_AutoRowIndex(object sender, DataGridViewRowPostPaintEventArgs e)
{
if (sender is DataGridView)
{
try
{
DataGridView dgv = sender as DataGridView;
if (dgv != null && dgv.RowHeadersVisible && dgv.Rows.Count > 0 && e.RowIndex >= 0)
{
String rowIdx = (AutoIndexStartNo + e.RowIndex).ToString();
StringFormat centerFormat = new StringFormat()
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
RectangleF headerBounds = new RectangleF(e.RowBounds.Left, e.RowBounds.Top, dgv.RowHeadersWidth, e.RowBounds.Height);
e.Graphics.DrawString(rowIdx, dgv.Font, SystemBrushes.ControlText, headerBounds, centerFormat);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
}
/// <summary>
/// 칼럼별 출력 방식 설정하기
/// </summary>
/// <param name="formats">칼럼별 출력 방식</param>
public void SetColumnAligns(List<DataGridViewContentAlignment> formats)
{
if (formats != null && formats.Count > 0)
{
if (m_lstColumnAligns != null)
{
m_lstColumnAligns.Initialize();
m_lstColumnAligns = null ;
}
m_lstColumnAligns = formats.ToArray();
}
}
/// <summary>
/// 바인딩 리스트를 출력하기
/// </summary>
/// <param name="sb">저장할 문자열 목록</param>
/// <param name="limit">한계 행 갯수 (0이면 무시, 0보다 클때만 적용됨)</param>
/// <param name="bDebug">디버깅창에 출력만 할 것인지 여부</param>
public void OutputBindingToList(out StringBuilder sb, int limit = 0, bool bDebug = true)
{
sb = new StringBuilder();
if (BindingToList != null)
{
foreach (object[,] v in BindingToList)
{
int nRow = v.GetLength(0);
int nCol = v.GetLength(1);
for (int r = 0; r < nRow; r++)
{
if (limit > 0 && r >= limit)
break;
string s = $"[{r + 1}] ";
for (int c = 0; c < nCol; c++)
s += $"{v[r, c].ToString()}, ";
if (!bDebug)
sb.AppendLine(s);
Debug.WriteLine(s);
}
}
}
}
#endregion
}
}