2010-02-16 6 views
3

현재 TabPage을 포함하는 TabControl의 양식이 있습니다. 각 TabPage에는 유효성 검사 논리와 적절한 ErrorProvider의 여러 컨트롤이 있습니다. 내 OK_Button_Clicked 이벤트에서 양식을 저장하고 닫을 지 여부를 결정하기 위해 Form.ValidateChildren()으로 전화합니다. 이제 탭 1에서 유효성 검사에 실패했지만 현재 보이는 탭이 탭 2 인 컨트롤이 있다고 가정합니다. 사용자가 확인을 누르면 폼이 닫히지 않는 이유에 대한 시각적 표시가 표시되지 않습니다. 유효성 검사가 실패한 탭으로 자동 전환 할 수 있기를 바라며 사용자는 ErrorProvider의 오류 표시를 볼 수 있습니다.WinForms TabControl 유효성 검사 : 유효성 검사가 실패한 탭으로 전환

하나의 접근법은 모든 적절한 컨트롤의 Validatedvalidating 이벤트를 구독하고 각 탭이 어느 탭에 있는지 알고 있으면 유효성 검사에 실패 할 때마다 유효성 검사에 실패한 탭 목록을 작성할 수 있습니다. ValidationFailed 이벤트가 내가 아는 한 생성되므로 성가신 수 있습니다 (예 : 각 컨트롤에 대해 부울을 정의하고 유효성 검사 전에 false로 설정하고 Validated 이벤트에서 true로 설정). 그리고 이러한 이벤트가 발생하더라도 유효성 검사에 실패 할 수있는 각 컨트롤에 대해 하나씩 많은 유효성 검사 이벤트를 듣고 유효성 검사되지 않은 탭 목록을 코드에 유지해야합니다. 여기에 포함 된 컨트롤에 유효성 검사가 실패하더라도 유효성 검사를 통과하기 때문에 TabPage의 유효성 검사 이벤트를 직접 구독하지 않는 것이 좋습니다.

또 다른 접근 방식은 내 TabPage의 컨트롤이 사용자 지정 컨트롤 일 수 있다는 사실을 활용할 수 있습니다.

public void OK_Button_Click 
{ 
    if (form.ValidateChildren()) 
     this.Close() 
    else 
     foreach (TabPage tab in this.TabControl) 
      foreach (Control control in tab.Controls) 
      { 
       ValidationInfo = control as ILastValidationInfoProvider 
       if (ValidationInfo != null && !ValidationInfo.LastValidationSuccessful) 
       { 
        this.TabControl.SelectTab(tab); 
        return; 
       } 
      } 
} 

: ValidateChildren에 대한 호출 내가 같은 코드를 사용할 수 있습니다 후, 다음

public MyControl : UserControl, ILastValidationInfoProvider 
{ 
    MyControl_Validing(object sender, object sender, CancelEventArgs e) 
    { 
     if (this.PassesValidation()) 
      this.ErrorProvider.SetError(sender, null); 
      LastValidationSuccessful = true; 
     else 
      e.Cancel = true; 
      this.ErrorProvider.SetError("Validation failed!", null); 
      LastValidationSuccessful = false; 
    } 
} 

그리고 :

interface ILastValidationInfoProvider 
{ 
    public bool LastValidationSuccessful {get; set;} 
} 
예를 들어

: 그때 그들과 같은 인터페이스를 구현 할 수있다 이 접근 방식이 더 좋지만 유효성 검사를받는 컨트롤이 사용자 지정이 아닌 경우를 처리하지 않습니다.

나는 더 나은 접근 방식을 기꺼이 사용할 것입니다. 어떤 아이디어?

(자신의 윈폼 책에서 크리스 판매 권장) 내가 Form.AutoValidate = EnableAllowFocusChange을 사용하고 편집, 그래서 초점은 실제로 (다른 탭으로 이동 포함) 유효성 검증에 실패 컨트롤에서 변경할 수 있습니다. 또한 사용자 정의 컨트롤의 샘플 코드를 업데이트하여 ErrorProvider이 내부에 있다는 사실을 강조했습니다.

답변

3

좋아요. 그래서 마침내 알아 냈습니다.

키가 TabPages이고 값이 HashSets이고 해당 탭 내에 유효하지 않은 컨트롤이 있습니다. 이 작업은 각 탭의 컨트롤에 대한 유효성 검사 및 유효성 검사 이벤트를 모두 구독하면 쉽게 수행 할 수 있습니다. 마지막으로 OK_BUtton_Click에서 ValidateChildren이 실패하는 경우 해시 세트 중 하나가 비어 있지 않으며 현재 유효하지 않은 첫 번째 탭으로 이동합니다 (현재 선택된 탭에 오류가없는 경우에만 해당).

Dictionary<TabPage, HashSet<Control>> _tabControls 
          = new Dictionary<TabPage, HashSet<Control>>(); 

    public OptionsForm() 
    { 
     InitializeComponent(); 
     RegisterToValidationEvents(); 
    } 

    private void RegisterToValidationEvents() 
    { 
     foreach (TabPage tab in this.OptionTabs.TabPages) 
     { 
      var tabControlList = new HashSet<Control>(); 
      _tabControls[tab] = tabControlList; 
      foreach (Control control in tab.Controls) 
      { 
       var capturedControl = control; //this is necessary 
       control.Validating += (sender, e) => 
        tabControlList.Add(capturedControl); 
       control.Validated += (sender, e) => 
        tabControlList.Remove(capturedControl); 
      } 
     } 
    } 

    private void Ok_Button_Click(object sender, EventArgs e) 
    { 
     if (this.ValidateChildren()) 
     { 
      _settings.Save(); 
      this.Close(); 
     } 
     else 
     { 
      var unvalidatedTabs = _tabControls.Where(kvp => kvp.Value.Count != 0) 
               .Select(kvp => kvp.Key); 
      TabPage firstUnvalidated = unvalidatedTabs.FirstOrDefault(); 
      if (firstUnvalidated != null && 
       !unvalidatedTabs.Contains(OptionTabs.SelectedTab)) 
        OptionTabs.SelectedTab = firstUnvalidated; 
     } 
    } 

나는 꽤 달콤하다고 생각합니다.

관련 문제