2012-01-11 6 views
0

Windows 응용 프로그램에서 사용할 확장 메서드 라이브러리를 만들고 있습니다. 내가 만들려고하는 방법 중 하나는 입력 컨트롤의 오류 상태를보다 쉽게 ​​설정하도록하는 것입니다.런타임에 Windows Form에서 ErrorProvider를 찾습니다.

public static void SetError(this System.Windows.Forms.TextBox textBox, string errorMessage) 
{ 
    if (string.IsNullOrEmpty(errorMessage)) 
    { 
     //reset control state 
     textBox.BackColor = System.Drawing.SystemColors.WindowText; 
    } 
    else 
    { 
     //set background colour to a nice shade of red 
     textBox.BackColor = System.Drawing.Color.MistyRose; 
    } 

    //try to locate an ErrorProvider on the control's containing form. 
    var errorProvider = LocateErrorProvider(textBox); 

    if (errorProvider != null) 
    { 
     //set error message on error provider (or clear it) 
     errorProvider.SetError(textBox, errorMessage); 
    } 
} 

나는 LocateErrorProvider 방법을 알아 내려고하고 있습니다. 내가하고 싶은 것은 ErrorProvider가 내 양식에 존재하는지 확인한 다음 존재하는 경우에만이를 사용하는 것입니다.

ErrorProvider는 Component이고 Control이 아니므로 form.Controls 속성을 통해 연결할 수 없습니다. 부모 양식을 다양한 개체로 캐스팅하려했지만 아무 소용이 없었습니다.

UPDATE : 나는 다음과 같은 코드를 사용하여 반사를 사용하여 ErrorProvider에 도착 처리했다 : 개인적으로

private static System.Windows.Forms.ErrorProvider GetErrorProvider(System.Windows.Forms.Control control) 
{ 
    //get the containing form of the control 
    var form = control.GetContainerControl(); 

    //use reflection to get to "components" field 
    var componentField = form.GetType().GetField("components", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); 

    if (componentField != null) 
    { 
     //get the component collection from field 
     var components = componentField.GetValue(form); 

     //locate the ErrorProvider within the collection 
     return (components as System.ComponentModel.IContainer).Components.OfType<System.Windows.Forms.ErrorProvider>().FirstOrDefault(); 
    } 
    else 
    { 
     return null; 
    } 
} 

을, 나는에 도착하기 위해 하드 코딩 된 필드 이름을 사용하여 너무 좋아 아니에요 들. 그러나이 경우에는 잘 작동하는 것 같습니다. 누구나 같은 결과를 얻을 수있는 더 좋은 방법이 있습니까?

+0

는'Dispose' 방법의 기본 구현에 사용되는'components' 수집있다. 그것이'private'인지'protected'인지는 기억하지 못합니다.하지만 같은 클래스의 객체에서 접근하기 때문에 중요하지 않습니다. –

+0

@Cody Grey : 고마워, 나는 그 분야에 도전하려고 노력했지만, 도전이되고있다. 이는 'System.Windows.Forms.Form'에 암시 적으로 묶여있는 컬렉션이 아니라 Visual Studio에서 Form 클래스에 추가 한 디자인 타임 변수입니다. 필자는 리플렉션을 사용하여 해당 필드에 접근하려고 시도했지만 ErrorProvider를 "엿볼"수 있었지만 실제로 아직 "얻을 수있는"것은 아닙니다. – tobias86

+0

리플렉션을 사용하여 오류 공급자에게 접근 할 수있었습니다. 누군가 다른 방법이 있다면 답을 게시하십시오! – tobias86

답변

3

지금까지 , 내 문제를 해결하는 것 :

private static System.Windows.Forms.ErrorProvider GetErrorProvider(System.Windows.Forms.Control control) 
{ 
    //get the containing form of the control 
    var form = control.GetContainerControl(); 

    //use reflection to get to "components" field 
    var componentField = form.GetType().GetField("components", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); 

    if (componentField != null) 
    { 
     //get the component collection from field 
     var components = componentField.GetValue(form); 

     //locate the ErrorProvider within the collection 
     return (components as System.ComponentModel.IContainer).Components.OfType<System.Windows.Forms.ErrorProvider>().FirstOrDefault(); 
    } 
    else 
    { 
     return null; 
    } 
} 

한스 & 코디의 훌륭한 아이디어 덕분입니다.

1

이것은 설계된 인터페이스입니다. 그들은 행동을 구현하는 클래스를 시행합니다. 여기에서 원하는 동작은 폼이 ErrorProvider를 갖는 것입니다. 인터페이스 구현

public interface IHasErrorProvider { 
    ErrorProvider Provider { get; } 
} 

그리고 오류 공급자와 양식이 있습니다 : 그래서이 같은 인터페이스를 쓰기

public partial class Form1 : Form, IHasErrorProvider { 
    public ErrorProvider Provider { 
     get { return errorProvider1; } 
    } 
    // etc.. 
} 

오류 제공자를 검색하는 것은 이제 간단하다 :

private static ErrorProvider GetErrorProvider(Control control) { 
     var impl = control.FindForm() as IHasErrorProvider; 
     return impl != null ? impl.Provider : null; 
    } 
+0

나는이 아이디어가 마음에 든다. 유일한 문제는 내가 항상 폼 자체를 제어 할 수 없다는 것이다. 그래도 고마워! – tobias86

+2

폼을 제어 할 수 없으면 ErrorProvider를 가진 폼을 제어 할 수 없습니다. 그 결과는 똑같습니다. 당신은 null을 얻을 것입니다. –

+0

동의어, 그 이유는 errorprovider가있는 경우에만 사용하고 있지만 사용자가 양식에서 아무 것도 변경하지 않기를 바랍니다. 내 방법은 그 자체로 그것을 알아낼 필요가있다. 감사. – tobias86

0

는 VS2005이 작동 :

private static System.Windows.Forms.ErrorProvider GetErrorProvider(System.Windows.Forms.Control control) 
    { 
     try 
     { 
      //get the containing form of the control 
      System.Windows.Forms.IContainerControl form = control.GetContainerControl(); 

      //use reflection to get to "components" field 
      System.Reflection.FieldInfo componentField = form.GetType().GetField("components", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); 

      if (componentField != null) 
      { 
       //get the component collection from field 
       object components = componentField.GetValue(form); 
       object oReturn = null; 
       //locate the ErrorProvider within the collection 
       foreach (object o in ((System.ComponentModel.Container)components).Components) 
       { 
        if (o.GetType() == typeof(System.Windows.Forms.ErrorProvider)) 
        { 
         oReturn = o; 
         break; 
        } 
       } 
       return (ErrorProvider)oReturn; 
      } 
     } 
     catch 
     { 
      return null; 
     } 
     return null; 
    } 
관련 문제