26

他のビジュアル コントロールを管理する非ビジュアル コンポーネントがあります。

コンポーネントが動作しているフォームへの参照が必要ですが、取得方法がわかりません。

デザイナーにドロップするだけでコンポーネントを機能させたいので、親をコントロールとして指定してコンストラクターを追加するかどうかはわかりません。

私が持っていた他の考えは、コントロールとして親のプロパティを持ち、デフォルト値を「Me」にすることでした

どんな提案も素晴らしいでしょう

編集:

明確にするために、これはコントロールではなくコンポーネントです。ここを参照してください:ComponentModel.Component

4

10 に答える 10

27

[以下の ISite 手法は設計時にのみ機能することを理解することが重要です。ContainerControl は公開されており、値が割り当てられるため、VisualStudio は実行時に値を設定する初期化コードを記述します。サイトは実行時に設定されますが、そこから ContainerControl を取得できません]

非ビジュアル コンポーネントに対してそれを行う方法を説明する記事を次に示します。

基本的に、プロパティ ContainerControl をコンポーネントに追加する必要があります。

public ContainerControl ContainerControl
{
  get { return _containerControl; }
  set { _containerControl = value; }
}
private ContainerControl _containerControl = null;

Site プロパティをオーバーライドします。

public override ISite Site
{
  get { return base.Site; }
  set
  {
    base.Site = value;
    if (value == null)
    {
      return;
    }

    IDesignerHost host = value.GetService(
        typeof(IDesignerHost)) as IDesignerHost;
    if (host != null)
    {
        IComponent componentHost = host.RootComponent;
        if (componentHost is ContainerControl)
        {
            ContainerControl = componentHost as ContainerControl;
        }
    }
  }
}

これを行うと、ContainerControl はデザイナーによって含まれているフォームを参照するように初期化されます。リンクされた記事では、より詳細に説明しています。

実行方法を確認する良い方法は、Lutz Reflector などのツールで必要な動作と同様の動作をする .NET Framework の型の実装を調べることです。この場合、System.Windows.Forms.ErrorProvider は注目すべき良い例です。フォームを含むことを知る必要があるコンポーネントです。

于 2008-12-16T16:26:00.430 に答える
9

再帰呼び出しを使用して、コントロール チェーンを上っていきます。これをコントロールに追加します。

public Form ParentForm
{
    get { return GetParentForm( this.Parent ); }
}

private Form GetParentForm( Control parent )
{
    Form form = parent as Form;
    if ( form != null )
    {
        return form;
    }
    if ( parent != null )
    {
        // Walk up the control hierarchy
        return GetParentForm( parent.Parent );
    }
    return null; // Control is not on a Form
}

編集:これを入力していたときに質問を変更したようです。コンポーネントの場合、そのコンポーネントのコンストラクターはその親をパラメーターとして取り、親は構築時にこれを渡す必要があります。タイマーなど、他のいくつかのコンポーネントがこれを行います。

親コントロールをメンバーとして保存し、これの代わりに上記で提供した ParentForm プロパティで使用します。

于 2008-12-16T14:53:57.357 に答える
3

なんらかの方法で親コンテナを設定する必要があります。コンポーネントは単なるクラスであり、他のすべてと同じようにメモリに存在します。何かがそれを作成したとあなたに言わない限り、それはそれを作成したものの本当の文脈を持っていません。親コントロールプロパティを作成して設定します。

または、単にコントロールから派生してFindForm()を使用します。すべてのコントロールに表示可能なコンポーネントが必要なわけではありません

于 2008-12-16T15:56:12.770 に答える
2

入力を必要としないこのソリューションを見つけました。C# の場合、次のように実装しました。

public partial class RegistryManager : Component, ISupportInitialize
{

    private Form _parentForm;
    public Form ParentForm
    {
        get { return _parentForm;  }
        set { _parentForm = value; }
    }

    // Etc....

    #region ISupportInitialize
    public void BeginInit() {  }
    public void EndInit()
    {
        setUpParentForm();
    }
    private void setUpParentForm()
    {
        if (_parentForm != null) return; // do nothing if it is set
        IDesignerHost host;
        if (Site != null)
        {
            host = Site.GetService(typeof(IDesignerHost)) as IDesignerHost;
            if (host != null)
            {
                if (host.RootComponent is Form)
                {
                    _parentForm = (Form)host.RootComponent;
                }
            }
        }
    }
    #endregion
}

この方法では、ユーザーが ParentForm を設定できますが、親フォームによってデフォルトとして設定されます。

お役に立てば幸いです。

于 2012-09-19T09:26:49.990 に答える
2

コンポーネントが他のビジュアル コントロールを管理している場合、それらを介して親にアクセスできるはずです。

于 2008-12-16T15:24:59.307 に答える
1

IComponent の Site プロパティを使用したいと思います。これは多かれ少なかれ Parent プロパティと同等です。

于 2008-12-16T15:02:35.170 に答える
1

ありがとうロブ、VB.Netプログラムであなたのソリューションを使用しました。次のようになります。

''' <summary>
''' Returns the parent System.Windows.form of the control
''' </summary>
''' <param name="parent"></param>
''' <returns>First parent form or null if no parent found</returns>
''' <remarks></remarks>
Public Shared Function GetParentForm(ByVal parent As Control) As Form
    Dim form As Form = TryCast(parent, Form)
    If form IsNot Nothing Then
        Return form
    End If

    If parent IsNot Nothing Then
        ' Walk up the control hierarchy
        Return GetParentForm(parent.Parent)
    End If

    ' Control is not on a Form
    Return Nothing
End Function

私のブログで参照しました: http://www.dailycode.info/Blog/post/2012/07/03/How-to-get-a-user-controls-parent-form-(Windows-forms).aspx

于 2012-07-03T13:17:52.437 に答える
-2

関連するコンポーネントFormがアクティブなForm場合は、 で取得できますForm.ActiveForm

于 2016-12-17T12:49:45.003 に答える
-3

上記の改善は次のとおりです。

public static Form ParentForm(this Control ctrl) => ctrl as Form ?? ctrl.FindForm();
于 2016-05-22T05:14:30.180 に答える