[WinForm] DataGridView – DataTable, List

[WinForm] DataGridView – DataTable, List

개요

이번 글에서는 DataGridView에 DataTable과 List<T> 요소를 표시하는 방법에 대해 알아보겠습니다.
DataGridView는 WinForm에서 데이터베이스, 컬렉션, 배열, DataTable 등의 데이터를 테이블 형태로 표시하기 위한 컨트롤 입니다.
이 컨트롤은 데이터를 행과 열로 이루어진 그리드에 표시하여 데이터를 표시하고 셀을 수정하여 데이터를 효율적으로 편집할 수 있습니다.

DataGridView는 아래와 같은 특징을 가지고 있습니다.

특징설명
데이터 바인딩DataTable, List<T> 등 데이터 소스와 연결
편집셀(Cell) 값을 직접 수정
정렬 및 필터링컬럼을 기준으로 데이터 정렬
스타일배경색, 글꼴, 행 높이, 열 너비 등 다양한 스타일 지정

DataTable을 DataGridView에 표시

DataGridView를 추가해보겠습니다. WinForm에 DataGridViewLabel을 추가해줍니다. 각각 컨트롤의 Name은 dataGridView, lbSelect로 만들어 줍니다.

DataTable을 연결하기 전에 우선 Load 이벤트 함수에 아래와 같이 DataTable을 만들어 주고 DataSource에 연결해줍니다.

private void Form1_Load(object sender, EventArgs e)
{
    // DataTable 생성
    m_table.Columns.Add("Name", typeof(string));
    m_table.Columns.Add("Price", typeof(int));

    m_table.Rows.Add("Apple", 1200);
    m_table.Rows.Add("Banana", 1000);
    m_table.Rows.Add("Blueberry", 1700);
    m_table.Rows.Add("Cherry", 2500);
    m_table.Rows.Add("Melon", 3000);

    dataGridView.DataSource = m_table; // DataTable 연결
}

실행하면 아래와 같이 표시됩니다.

몇 가지 속성을 이용하면 크기나, 다중 선택, 편집 불가능하게 가능합니다. 아래는 자주 사용하는 속성에 대한 설명입니다.

속성설명
Dock위치 및 크기 조정 방법 (Fill, Top, Bottom, Left, Right, None 등)
AllowUserToAddRows사용자가 새로운 행을 추가할 수 있도록 허용 여부 (true = 허용, false = 불가능)
AllowUserToDeleteRows사용자가 행을 삭제할 수 있도록 허용 여부 (true = 허용, false = 불가능)
AutoSizeColumnsMode열 크기 자동 조정 방식 (Fill, AllCells, DisplayedCells, None 등)
SelectionMode셀 또는 행/열 선택 방식 (FullRowSelect, CellSelect, ColumnHeaderSelect 등)
MultiSelect여러 개의 행 또는 셀을 동시에 선택할 수 있도록 허용 여부 (true = 다중 선택, false = 단일 선택)
ReadOnlyDataGridView의 전체 데이터를 읽기 전용으로 설정 (true = 편집 불가능, false = 편집 가능)

Load 함수에 아래와 같이 속성을 추가합니다.

dataGridView.Dock = DockStyle.Fill; // 화면에 채우기
dataGridView.AllowUserToAddRows = false; // 사용자가 행 추가 막기
dataGridView.AllowUserToDeleteRows = false; // 사용자가 행 삭제 가능한지
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; // 표시되는 열의 자동 크기 조정 모드. 열 채우기
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect; // 셀 선택 모드. 모든 행 선택
dataGridView.MultiSelect = true; // 여러 줄 선택
dataGridView.ReadOnly = true; // 읽기 전용

이 코드가 추가된 상태로 실행하면 아래와 같이 표시합니다.

스타일 변경

DataGridView의 스타일을 변경하는 속성도 있습니다. 아래는 스타일과 관련 된 속성에 대한 설명입니다.

속성설명
BackgroundColorDataGridView의 전체 배경 색을 설정하는 속성
GridColorDataGridView의 셀 테두리(그리드 라인)의 색상을 설정
RowHeadersDefaultCellStyle행 헤더(왼쪽 번호 부분)의 기본 스타일(배경색, 글꼴 등)
ColumnHeadersDefaultCellStyle열 헤더(상단 제목 부분)의 기본 스타일(배경색, 글꼴 등)
DefaultCellStyle데이터 셀의 기본 스타일(배경색, 글꼴, 정렬 등)
AutoSizeColumnsMode열 크기 자동 조정 방식 설정 (Fill, AllCells, DisplayedCells 등)
AutoSizeRowsMode행 크기 자동 조정 방식 설정 (AllCells, DisplayedCells 등)
CellBorderStyle셀 테두리 스타일 (Single, None, Raised, Sunken 등)
RowHeadersBorderStyle행 헤더 테두리 스타일 (Raised, Sunken, None 등)
ColumnHeadersBorderStyle열 헤더 테두리 스타일 (Raised, Sunken, None 등)
AlternatingRowsDefaultCellStyle번갈아 표시되는 행(홀/짝수)의 스타일을 다르게 지정 (줄무늬 효과)

아래와 같이 Load 이벤트 함수에 입력 하면 스타일이 변경 되는 것을 볼 수 있습니다.

// 배경색 및 기본 스타일 설정
dataGridView.BackgroundColor = Color.LightGray;  // 전체 배경색
dataGridView.GridColor = Color.DarkGray;        // 셀 테두리 색상

// 행 스타일 변경
dataGridView.RowHeadersDefaultCellStyle.BackColor = Color.Navy;
dataGridView.RowHeadersDefaultCellStyle.ForeColor = Color.White;

// 컬럼 헤더 스타일 변경
dataGridView.ColumnHeadersDefaultCellStyle.BackColor = Color.DarkBlue;
dataGridView.ColumnHeadersDefaultCellStyle.ForeColor = Color.White;

// 선택된 행 스타일 변경
dataGridView.DefaultCellStyle.SelectionBackColor = Color.DarkCyan;
dataGridView.DefaultCellStyle.SelectionForeColor = Color.White;

// 행 높이 및 열 너비 자동 조정
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; // 열 너비 자동 조절
dataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;  // 행 높이 자동 조절

// 행 및 열 테두리 스타일 변경
dataGridView.CellBorderStyle = DataGridViewCellBorderStyle.SingleHorizontal;
dataGridView.RowHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;
dataGridView.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single;

실행 하면 아래와 같이 스타일이 변경 된 것을 볼 수 있습니다.

이벤트 함수

DataGridView에서 자주 사용하는 함수 몇 가지만 알아보도록 하겠습니다.

함수명설명
CellClick사용자가 셀을 클릭할 때 발생하는 이벤트
CellValueChanged셀의 값이 변경될 때 발생하는 이벤트. 변경 후 포커스가 다른 곳으로 이동해야 이벤트가 발생
SelectionChanged사용자가 선택한 셀, 행, 열이 변경될 때 발생하는 이벤트. 마우스 클릭, 키보드 이동 등 다양한 상황에서 발생

위에서 설정한 속성 SelectionMode, MultiSelect, ReadOnly를 주석 처리 해주고, 각 이벤트 함수를 아래와 같이 코딩해줍니다.

private void Form1_Load(object sender, EventArgs e)
{
    // ....

    //dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect; // 셀 선택 모드. 모든 행 선택
    //dataGridView.MultiSelect = true; // 여러 줄 선택
    //dataGridView.ReadOnly = true; // 읽기 전용

    // ....
}

private void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
    // cell 클릭
    if ((0 <= e.RowIndex && e.RowIndex < dataGridView.Rows.Count) &&
        (0 <= e.ColumnIndex && e.ColumnIndex < dataGridView.Columns.Count))
    {
        string? strVal = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
        if (strVal != null)
        {
            textBox.AppendText(Environment.NewLine);
            textBox.AppendText($"[{e.RowIndex}, {e.ColumnIndex}] 셀 클릭: {strVal}");
        }
    }
}

private void dataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    // 셀 값 변경 시 호출
    textBox.AppendText(Environment.NewLine);
    textBox.AppendText($"[{e.RowIndex}, {e.ColumnIndex}] 값 변경됨: {dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value}");
}

private void dataGridView_SelectionChanged(object sender, EventArgs e)
{
    // row 클릭
    StringBuilder sbTotal = new StringBuilder();
    foreach (DataGridViewRow row in dataGridView.SelectedRows)
    {
        StringBuilder sbRow = new StringBuilder();
        foreach (DataGridViewCell cell in row.Cells)
        {
            string? strVal = cell.Value.ToString();
            if (strVal != null)
            {
                if (0 < sbRow.Length)
                    sbRow.Append(",");
                sbRow.Append(strVal);
            }
        }
        string strRow = $"{row.Index}: {sbRow.ToString()}";
        sbTotal.AppendLine(strRow);
    }

    if (0 < sbTotal.Length)
    {
        string strTotal = "SelectionChanged" + Environment.NewLine + sbTotal.ToString();
        textBox.AppendText(Environment.NewLine);
        textBox.AppendText(strTotal);
    }
}

실행하면 아래와 같이 표시합니다.

DataGridView – List<T>

어떠한 객체를 List에 담아 DataGridView에 표현하는 방법을 알아보겠습니다. 우선 CPerson 클래스를 하나 만들어줍니다.

class CPerson
{
    private string m_strName;
    private int m_iAge;

    public CPerson(string strName, int iAge = 0)
    {
        m_strName = strName;
        m_iAge = iAge;
    }

    public string NAME { set => m_strName = value; get => m_strName; }
    public int AGE { set => m_iAge = value; get => m_iAge; }
}

그 다음 Load 이벤트 함수에 아래와 같이 입력합니다.

private void Form1_Load(object sender, EventArgs e)
{
    // List로 추가
    List<CPerson> persons = new List<CPerson>();
    persons.Add(new CPerson("Jake", 10));
    persons.Add(new CPerson("David", 12));
    persons.Add(new CPerson("Rachel", 20));

    dataGridView.DataSource = persons;
}

실행하면 정상 표시합니다.

칼럼을 보면 NAME, AGE 속성 문자열 그대로 사용합니다. List<T>일 경우엔 데이터를 연결하기 전에, DataGridView 칼럼을 자동 생성하지 않고 직접 칼럼을 생성하여 속성 이름과 그 속성의 표시를 설정 해줘야 합니다.

private void Form1_Load(object sender, EventArgs e)
{
    // 칼럼
    dataGridView.AutoGenerateColumns = false; // 칼럼 자동 생성 false 설정

    DataGridViewTextBoxColumn colName = new DataGridViewTextBoxColumn
    colName.DataPropertyName = "NAME"; // 속성 이름
    colName.HeaderText = "Person Name"; // 헤더 표시

    DataGridViewTextBoxColumn colBirth = new DataGridViewTextBoxColum
    colBirth.DataPropertyName = "AGE"; // 속성 이름
    colBirth.HeaderText = "Person Age"; // 헤더 표시

    dataGridView.Columns.Add(colName);
    dataGridView.Columns.Add(colBirth);

    // List로 추가
    List<CPerson> persons = new List<CPerson>();
    persons.Add(new CPerson("Jake", 10));
    persons.Add(new CPerson("David", 12));
    persons.Add(new CPerson("Rachel", 20));

    dataGridView.DataSource = persons;
}

실행하면 칼럼 텍스트가 바뀐 것을 볼 수 있습니다.

이상으로 DataGridView에 대해 알아보았습니다.


github : https://github.com/3001ssw/c_sharp/tree/main/WinForm/DataGridView