c# DataGridView의 공유 행 – shared rows
아래는 행 인스턴스를 만들어 DataGridView에 추가한 뒤 DataGridView의 행이 아닌 추가를 위해 만든 인스턴스에 액세스하는 예제다. System.ArgumentOutOfRangeException 처리가 되며 Specified argument was out of the range of valid values. Arg_ParamName_Name라는 메시지가 뜬다. 클래스의 인스턴스를 만들어서 List에 넣으면 List에 들어간 아이템과 여기에 넣으려고 만든 인스턴스는 같다. 인스턴스를 수정하면 리스트의 아이템도 수정된다. 그러나 DataGridViewRow와 DataGridView의 관계는 이렇지 않다. DataGridView에 추가된 DataGridViewRow는 인덱스와 칼럼 정보 등 DataGridView와 관련된 정보들을 갖게 되지만 추가된 인스턴스는 그렇지 않다. 따라서 이러한 인스턴스에서 인덱스를 읽어 봐야 제대로 된 값이 아닌 것이다.
private void button1_Click(object sender, EventArgs e)
{
dataGridView1.Columns.Add("column 0", "column 0");
DataGridViewRow dataGridViewRow = new();
int rowIndex = dataGridView1.Rows.Add(dataGridViewRow);
textBox1.AppendText(rowIndex.ToString() + "\r\n"); // 0
textBox1.AppendText(dataGridViewRow.Index.ToString()); // -1
dataGridViewRow.Cells["column 0"].Value = "row 0"; // exception
}
DataGridView는 이미 많은 자원을 필요로 하는 무거운 객체인데 여기다 많은 행들까지 제어하려 하면 제대로 작동하기 어렵게 된다. 이런 문제를 피하기 위해 .네트는 여러 방법들을 이용하는데 그 가운데 하나가 shared rows라는 거다. 칼럼열들은 일반적으로 그 수가 제한적인 데에 반해 행들은 무지 많다. 이런 행들이 각자 인스턴스를 갖고 메모리를 차지한다는 건 그냥 대충 생각해 봐도 좀 아니다 싶다. 그래서 DataGridViewRow 하나가 모든 행들을 대표한다. 많은 행들이 이거 하나를 인스턴스로 공유하는 거다. 예를 들어 각 행들의 높이를 변경하고 싶다면 DataGridViewRow의 높이만 변경하면 된다. 이때 DataGridViewRow는 DataGridView에 있는 하나의 행이 아니므로 0 이상의 정수인 인덱스를 갖지 않고 인덱스는 -1이다.
DataGridView에 포함된 각 행은 인덱스로 액세스해야 한다. 그러나 위의 내용은 DataTable에는 적용되지 않는다. DataTable에 들어가는 행인 DataRow는 위와 같이 new()로 만들 수 없고 아래와 같이 해야 한다. 따라서 DataGridViewRow 인스턴스의 공유 문제가 생길 여지가 없다. 행 인스턴스가 생기면서 동시에 테이블로 들어가기 때문이다.
private void Form1_Load(object sender, EventArgs e)
{
DataTable dataTable = new();
dataTable.Columns.Add();
DataRow dataRow = dataTable.NewRow();
}