web-dev-qa-db-ja.com

コンポーネントの親フォームを取得する

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

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

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

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

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

編集:

明確にするために、これはcontrolではなくcomponentです、ここを参照してください: ComponentModel.Component

25
Pondidum

[以下の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はその良い例です。含まれているフォームを知る必要があるコンポーネントです。

27
Joe

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

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プロパティで使用します。

9
Rob Prouse

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

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

3
Brian Rudolph

私は this solution を見つけました。これは入力を必要としません。 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を設定できますが、親フォームによってデフォルトとして設定されます。

お役に立てば幸いです。

2
Vaclav Svara

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

2
BFree

これを試して ....

_private Form GetParentForm(Control parent)
{
    if (parent is Form)
        return parent as Form;

    return parent.FindForm();
}
_

コンポーネントからGetParentForm(this.Parent)を呼び出す

1
sandipmatsagar

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

1
arul

ありがとうロブ、私は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

1
Mark