2014-01-31 3 views
0

감사합니다.제어 목록에서 컨트롤을 삭제하고 읽을 수 없습니다.

메인 패널의 컨트롤을 전환하는 버튼이있는 C# .NET 폼이 있습니다. Visual Studio 2012 및 고급 설치 관리자로 업그레이드 할 때까지 아무런 문제가 없었습니다. 타겟 프레임 워크는 4.5가 아닌 4.0입니다.

컨트롤을 변경하면 새 컨트롤을 추가하기 전에 이전 컨트롤을 삭제하고 제거하지만 아직 컨트롤이 없으면 (즉, 첫 번째 컨트롤이로드 될 때) 오류가 발생합니다.

원래 루프가 컬렉션을 수정하는 동안 반복에 대해 무언가와 충돌 했으므로 이제는 컨트롤을 제거한 후 제거하려고합니다.

이 오류는 다음과 같습니다. 인덱스 0이 범위를 벗어났습니다.

이 모든 것이 dev 컴퓨터에서 정상적으로 작동하며 이전의 기본 제공 VS 설치 프로그램을 사용하여 문제가되지 않았습니다.

아이디어가 있으십니까? 4.0 프레임 워크 문제? 누락 된 참조가 배포되지 않습니까?

감사합니다.

panelMain.SuspendLayout(); 
int control_count = panelMain.Controls.Count; 
if (control_count > 1) { 
    Log.Write("More than one control found in main panel.", ErrorLevel.Error); 
} 
if (control_count > 0) { 
    Control current_ctrl = panelMain.Controls[0]; 
    current_ctrl.Dispose(); 
    panelMain.Controls.Remove(current_ctrl); 
} 

//foreach (Control ctrl in panelMain.Controls) { 
// ctrl.Dispose(); 
// panelMain.Controls.Remove(ctrl); 
//} 

답변

2

당신이 주석 한 foreach 루프와 문제는 당신이 현재 열거되는 컬렉션 항목에 항목을 추가하거나 제거 할 수 없다는 것입니다. 즉, 컬렉션을 반복하고 항목을 제거하려면 for 루프를 사용해야합니다. 여러 항목을 제거하려면 뒤로를 반복해야합니다.

두 번째 if 문과 관련된 문제는 컨트롤을 삭제하면 부모 컨트롤의 컬렉션에서 자동으로 제거된다는 것입니다. 즉, 컨트롤에서 Dispose를 호출하면 더 이상 컨트롤 컬렉션에 항목이 없으므로 Remove 호출이 실패합니다.

그래서 이야기의 도덕은 for 루프를 사용하고 거꾸로 반복하고 Dispose를 사용하여 삭제하고 제거해야한다는 것입니다.

0

관심있는 사람이 있다면 컨트롤을 처리하는 간단한 재귀 적 방법입니다. 위의 jmcilhinney의 조언을 사용하십시오.

참고 : Visible 속성에 대한 모든 의견을 읽고 다시 true로 설정해야합니다.

// Start by calling a parent control containing the controls you want to 
    // destroy such as a form, groupbox or panel 
    private void DisposeControls(Control ctrl) 
    { 
     // Make control disappear first to avoid seeing each child control 
     // disappear. This is optional (if you use - make sure you set parent 
     // control's Visible property back to true if you create controls 
     // again) 
     ctrl.Visible = false; 
     for (int i = ctrl.Controls.Count - 1; i >= 0; i--) 
     { 
      Control innerCtrl = ctrl.Controls[i]; 

      if (innerCtrl.Controls.Count > 0) 
      { 
       // Recurse to drill down through all controls 
       this.DisposeControls(innerCtrl); 
      } 

      innerCtrl.Dispose(); 
     } 
    }