2012-01-11 8 views
0

私はWindowsフォームアプリケーションで使用する拡張メソッドライブラリを作成しています。私が作成しようとしているメソッドの1つは、入力コントロールのエラー状態をより簡単に設定できるようにすることです。実行時にWindowsフォームで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; 
    } 
} 

Hans &コディに感謝します。 VS2005で

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

これは動作します:

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; 
    } 
関連する問題