15

Windows フォームで使用されるすべてのコントロールのリストを見つけて収集する方法を知っています。このようなもの:

static public void FillControls(Control control, List<Control> AllControls)
{
    String controlName = "";
    controlName = control.Name;

    foreach (Control c in control.Controls)
    {
        controlName = c.Name;
        if ((control.Controls.Count > 0))
        {
            AllControls.Add(c);
            FillControls(c, AllControls);
        }
    }
}

ただし、この関数は、フォームの下部にある HelpProvider、ImageList、TableAdapters、DataSets などの非ビジュアル コンポーネントを取得しません。

これらのコンポーネントのリストも取得する方法はありますか?

編集:

同様の関数で代わりに System.ComponentModel.Component を使用するように指摘してくれた @HighCore に感謝し、ImageList、Help Provider、BindingSource などのコンポーネントを含むリストを取得します。ただし、このリストにはまだ TableAdapters と DataSet が含まれていません。それらはオブジェクトから直接継承されているためだと思います。

お願いします。私のものと同様の機能を示し、コントロールのリストのみを取得する古い投稿を参照しないでください。

編集:なぜ反対票なのですか?この質問はこれまでに答えられたことはありません!

4

2 に答える 2

16

驚くべきことに、これを行う唯一の方法はリフレクションを使用することです。

private IEnumerable<Component> EnumerateComponents()
{
    return from field in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
           where typeof (Component).IsAssignableFrom(field.FieldType)
           let component = (Component) field.GetValue(this)
           where component != null
           select component;
}
于 2013-06-18T15:47:29.473 に答える
1

デザイナによって構築されたすべてのコントロールには、タイプ IContainer の「コンポーネント」と呼ばれるプライベート フィールドが必要です。リフレクションを使用してこのフィールドの値を取得し (存在する場合)、コンポーネントを反復処理できます。

このメソッドは、コンポーネントとしてキャストできるすべてのフィールドではなく、デザイナーを使用してフォームに追加されたコンポーネントのみを返すという点で、他の回答とは異なります。

    public IEnumerable<Component> GetComponents(Control c)
    {
        FieldInfo fi = c.GetType()
            .GetField("components", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        if (fi?.GetValue(c) is IContainer container)
        {
            return container.Components.OfType<Component>();
        }
        else
        {
            return Enumerable.Empty<Component>();
        }
    }
于 2019-07-25T04:49:59.713 に答える