2008-10-22 4 views
0

는 I는 다음과 같이 (즉, 데이터 테이블/데이타베이스에 결합되지 않은) 프로그래밍 된 DataGridView의 열을 삽입하고 :Columns.Insert가 DataGridView (C#)에서 DisplayIndex를 업데이트하지 않는 이유는 무엇입니까?

int lastIndex = m_DGV.Columns.Count - 1; // Count = 4 in this case 
DataGridViewTextBoxColumn col = (DataGridViewTextBoxColumn)m_DGV.Columns[lastIndex]; 
m_DGV.Columns.RemoveAt(lastIndex); 
m_DGV.Columns.Insert(insertIndex, col); // insertIndex = 2 

I 찾은 내 열 가끔이 방법을 사용하여 순서가 시각적 있음. 해결 방법은 나중에 열의 DisplayIndex 속성을 수동으로 설정하는 것입니다. 이 코드를 추가하면 "수정"되지만, 왜 이런 식으로 행동하는지 이해할 수 없습니다.

Console.Write(m_DGV.Columns[0].DisplayIndex); // Has value of 0 
Console.Write(m_DGV.Columns[1].DisplayIndex); // Has value of 1 
Console.Write(m_DGV.Columns[2].DisplayIndex); // Has value of 3 
Console.Write(m_DGV.Columns[3].DisplayIndex); // Has value of 2 
col.DisplayIndex = insertIndex; 
Console.Write(m_DGV.Columns[0].DisplayIndex); // Has value of 0 
Console.Write(m_DGV.Columns[1].DisplayIndex); // Has value of 1 
Console.Write(m_DGV.Columns[2].DisplayIndex); // Has value of 2 
Console.Write(m_DGV.Columns[3].DisplayIndex); // Has value of 3 

제 생각에는 그리드의 열 수를 동적으로 늘릴 수 있습니다. 나는 그것을 청크 (chunk) 단위로 자라려고했기 때문에 각 삽입은 열 할당 (및 연관된 초기화)을 필요로하지 않았다. 그 다음에 "new"열은 끝에 사용되지 않은 열을 가져 와서 원하는 위치에 삽입하고 표시함으로써 추가됩니다.

답변

2

DataGridView의 열 순서에 따라 표시 순서가 결정되는 것은 아니기 때문에 명시 적으로 할당하지 않아도 기본적으로 열 순서에 따라 DisplayIndex 속성 값이 결정되기 때문입니다. 그래서 DisplayIndex 속성이있어서 Insert를 수행하지 않고 컬렉션에 열을 추가 할 수 있습니다. DisplayIndex 값을 지정하면 DisplayIndex가 같거나 큰 모든 항목에 대해 계단식 업데이트가 수행됩니다. 귀하의 예제에서 삽입 된 열은 첫 번째 생략 된 DisplayIndex 값을 받고 있습니다. a question/answer에서

내가 발견

이동하는 이전 DisplayIndex 및 새 DisplayIndex 사이 모든 열을 일으킬 것이다 DisplayIndex 변경.

거의 모든 모음 (LinkedLists 제외)과 마찬가지로 항상 모음에 than insert into 컬렉션을 추가하는 것이 좋습니다. 보고있는 동작은 해당 규칙을 반영한 것입니다.

+0

또한 기본 Columns 데이터 구조와 DisplayIndex 사용에서 표시 순서가 분리되어 있기 때문에 열을 청크로 추가하여 최적화 할 필요가 없으며 사물을 복잡하게 만 만들 수 있습니다. – cfeduke

0

훌륭한 조언을 위해 cfeduke에게 감사드립니다. 나는 Insert이 더 느릴 것이라고 생각했지만, 제공된 링크는 나에게 다소 느리게 계몽되었다.

이렇게하면 DataGridView에서 열을 효율적으로 삽입하고 제거하는 방법에 대한 질문이 생깁니다. 이상적인 디자인은 Add 또는 AddRange을 사용하여 많은 양의 열을 추가 한 다음 실제로 제거하지 않는 것 같습니다. 그런 다음 Visible 속성을 false로 설정하여 제거를 시뮬레이션 할 수 있습니다. 그리고 보이지 않는 열을 잡아서 DisplayIndex으로 설정하고 열어서 열을 삽입 할 수 있습니다.

그러나이 방법으로 피할 지뢰가있을 것으로 생각됩니다. 가장 중요한 것은 더 이상 데이터를 직접적으로 색인 할 수 없다는 것입니다. 즉, m_DGV.Columns[i]m_DGV.Rows[n].Cells[i]은 올바르게 매핑되지 않습니다. 외부 직관적 인 매핑을 유지하기 위해지도/사전을 만들 수 있다고 가정합니다.

내 응용 프로그램 (현재 설계된)은 열을 자주 삽입하고 제거해야하므로 많은 가치가 있습니다. 누구든지 어떤 제안이 있습니까?

2

나는 몇 가지 아이디어가 있습니다.

  1. 컬렉션의 인덱스가 아닌 고유 한 이름으로 열을 지정하는 방법은 어떻습니까? 그들은 아직 이름이 없을 수도 있지만, 당신이 누군가에게 의미있는 이름을 주면 누가 누군지를 추적 할 수 있습니다.

  2. 당신이 사용할 수있는 GetFirstColumn, GetNextColumn, GetPreviousColumn, 표시 순서에 작업 DataGridViewColumnCollection 클래스의 GetLastColumn 방법, 컬렉션의 순서가 아니라. for 루프와 m_DGV.Columns[i]을 사용하여 원하는 컬렉션을 찾을 때까지 컬렉션을 반복 할 수 있습니다.

  3. 상속 된 DataGridViewDataGridViewColumnCollection을 만듭니다. DataGridView은 단순히 새 컬렉션 클래스를 사용하도록 재정의됩니다. 새로운 DataGridViewColumnCollection에는 디스플레이 색인별로 컬렉션을 처리하는 방법이 포함되어 있습니다. 원하는 인덱스를 찾을 때까지 컬렉션을 반복하는 것이 좋습니다 (# 2 참조). 또는 사전을 저장하고 매우 많은 수의 열에 대해 업데이트 된 상태로 유지할 수 있습니다.

    필자는 칼럼이 움직일 때마다 전체적인 것을 다시 써야하기 때문에 사전을 유지하는 것이 성능이 향상되는 것을 의심합니다. 어쨌든 반복은 O (n)이며, 수십 개의 컬럼으로 비동기 연산을 언급하지 않는다면 아마 괜찮을 것입니다.

    DataGridView이 엉망이 아닌 것으로 가정하면 this[] 연산자도 무시할 수 있습니다.

Idea # 1이 가장 구현하기 쉽지만 꼭 필요한 것은 아닙니다. 아이디어 # 2는 작동하며, 이것을 DataGridViewColumn GetColumnByDisplayIndex(int Index) 함수에 넣을 수 있습니다. Idea # 3은 귀엽고 확실히 캡슐화 된 접근 방식이지만 꼭 사소한 것은 아닙니다.

관련 문제