フォームデザイナ上でユーザーコントロールをコントロールコンテナとして利用する方法

この記事は公開から4年以上経過しています。

WinFormsのフォームデザイナ上でユーザーコントロールをコンテナとして利用するための手順です。

メインの解説はVB.NETを例としていますが、C#も同様に対応が可能です。
※現在プラグインの問題でクラスダイアグラムが表示されていません。

file

VisualStudioのフォームデザイナから、上図のようなパネル的な役割のユーザーコントロール上にボタンを配置するようなレイアウトを行なうと、意図したコントロールレイヤーとならない事によって描画時のチラツキやタブオーダーの問題が発生する場合があります。

・フォームデザイナでユーザーコントロール上にボタンを配置


フォーム上にユーザーコントロールを配置して、そのユーザーコントロール上にボタンを配置する場合、フォーム内のコントロールレイヤーは並列になります。

graph LR;
Form-->UserControl;
Form-->Button
    Private Sub InitializeComponent()
        Me.UserControl1 = New UserControl1()
        Me.Button1 = New System.Windows.Forms.Button()
        Me.SuspendLayout()
        '
        'UserControl1
        '
        Me.UserControl1.BackColor = System.Drawing.SystemColors.ActiveCaption
        Me.UserControl1.Location = New System.Drawing.Point(78, 77)
        Me.UserControl1.Name = "UserControl1"
        Me.UserControl1.Size = New System.Drawing.Size(383, 314)
        Me.UserControl1.TabIndex = 0
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(232, 223)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(75, 23)
        Me.Button1.TabIndex = 2
        Me.Button1.Text = "Button1"
        Me.Button1.UseVisualStyleBackColor = True
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(539, 468)
        Me.Controls.Add(Me.Button1) ' ←ボタンがフォームに追加される
        Me.Controls.Add(Me.UserControl1)    ' ←ユーザーコントロールがフォームに追加される
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)
    End Sub

・フォームデザイナでパネル(コンテナ)にボタンを配置


一方、フォーム上にパネルコントロールを配置して、そのパネル上にボタンを配置する場合、フォーム内のコントロールレイヤーは直列になります。

graph LR;
Form-->Panel;
Panel-->Button;
    Private Sub InitializeComponent()
        Me.Panel1 = New System.Windows.Forms.Panel()
        Me.Button1 = New System.Windows.Forms.Button()
        Me.Panel1.SuspendLayout()
        Me.SuspendLayout()
        '
        'Panel1
        '
        Me.Panel1.BackColor = System.Drawing.SystemColors.ActiveCaption
        Me.Panel1.Controls.Add(Me.Button1)' ←ボタンがパネルに追加される
        Me.Panel1.Location = New System.Drawing.Point(78, 85)
        Me.Panel1.Name = "Panel1"
        Me.Panel1.Size = New System.Drawing.Size(380, 278)
        Me.Panel1.TabIndex = 0
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(160, 149)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(75, 23)
        Me.Button1.TabIndex = 0
        Me.Button1.Text = "Button1"
        Me.Button1.UseVisualStyleBackColor = True
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(539, 468)
        Me.Controls.Add(Me.Panel1)' ←パネルがフォームに追加される
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.Panel1.ResumeLayout(False)
        Me.ResumeLayout(False)
    End Sub

・ユーザーコントロールのコンテナコントロール化方法


パネルと同様にユーザーコントロールをコンテナとして利用したい場合には、ユーザーコントロールにParentControlDesigner属性を設定します。

' VB.NET
Imports System.ComponentModel
Imports System.ComponentModel.Design

<Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", GetType(IDesigner))>
Public Class UserControl1

End Class
// C#
using System.ComponentModel;
using System.ComponentModel.Design;

[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public class UserControl1
{

}

コンテナ化したユーザーコントロール上にボタンを配置したときのコントロールレイヤーは以下のとおりです。

graph LR;
Form-->UserControl;
UserControl-->Button;
    Private Sub InitializeComponent()
        Me.UserControl1 = New UserControl1()
        Me.Button1 = New System.Windows.Forms.Button()
        Me.UserControl1.SuspendLayout()
        Me.SuspendLayout()
        '
        'UserControl1
        '
        Me.UserControl1.BackColor = System.Drawing.SystemColors.ActiveCaption
        Me.UserControl1.Controls.Add(Me.Button1)    ' ←ボタンがユーザーコントロールに追加される
        Me.UserControl1.Location = New System.Drawing.Point(78, 77)
        Me.UserControl1.Name = "UserControl1"
        Me.UserControl1.Size = New System.Drawing.Size(383, 314)
        Me.UserControl1.TabIndex = 0
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(155, 144)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(75, 23)
        Me.Button1.TabIndex = 2
        Me.Button1.Text = "Button1"
        Me.Button1.UseVisualStyleBackColor = True
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(539, 468)
        Me.Controls.Add(Me.UserControl1)' ←ユーザーコントロールがフォームに追加される
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.UserControl1.ResumeLayout(False)
        Me.UserControl1.PerformLayout()
        Me.ResumeLayout(False)
    End Sub

このようにデザイナ属性を設定することで簡単にコンテナコントロール化することが可能です。
但し、フォーム等へ配置したコンテナ化したユーザーコントロール上に別の部品を配置すると、ユーザーコントロールに元々存在するコントロールのAnchorが意図した振る舞いをしない等、コンテナ化の前後の挙動が変わるため注意が必要です。

以上です。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする