【学習】WinFormsでUserControlを使ってみよう(複数コントロールを1つにまとめる)

2026年8月29日

広告

Label、TextBox、Buttonを1つのUserControlにまとめ、複数の場所で再利用することを示す図

これまでの学習では、

  • フォームに1つずつコントロールを配置する
  • Button、TextBox、Label などを個別に使う

という形でプログラムを動かしてきました。

しかし、同じ組み合わせ(例:ラベル+テキストボックス+クリアボタン)を複数箇所で使いたい場面があります。

複数コントロールを1つにまとめて再利用する

という仕組みです。

今回は UserControl(ユーザーコントロール) を使って、「タイトル付きテキストボックス+クリアボタン」を1つの部品として作るアプリを作ります。

今日作るもの

「クリア可能なテキストボックス」 を UserControl として作成し、フォームに2つ配置します。

  •  と  の2つの入力欄
  • 各欄に「↻」ボタンがあり、押すとテキストがクリアされる
  • 両方入力すると「Hello 姓 名」と表示される

ソリューションとプロジェクトを作る

Visual Studio で新しいプロジェクトを作ります。

  • テンプレート: Windows Forms アプリ (.NET Framework)
  • ソリューション名: UserControlSample
  • プロジェクト名: UserControlDemo

作成すると Form1 が表示されます。


UserControl を追加する

  1. ソリューションエクスプローラーで プロジェクト名 を右クリック
  2. 追加 → ユーザー コントロール(Windows フォーム) を選択
  3. 名前を ClearableTextBox に設定して 追加 をクリック
  4. デザイナーが開き、白いデザイン画面が表示される

UserControl にコントロールを配置する

ClearableTextBox のデザイン画面に、次のコントロールを配置します。

コントロール名前プロパティ
LabellblTitleLocation: 3, 5
TextBoxtxtValueLocation: 3, 23、Size: 148, 23、Anchor: Top, Left, Right
ButtonbtnClearLocation: 157, 23、Size: 31, 23、Text: ↻、Anchor: Top, Right

UserControl の Size を 191, 53 に、MinimumSize を 84, 53 に設定します。

lblTitle の Text は空欄のままで構いません(フォーム側で Title プロパティで設定します)。

コントロールの配置例

次の図は配置の一例です。青いラベルを参考に、プロパティウィンドウで Name を設定してください。

UserControlDemoで使用するコントロールのForm1配置例

UserControl のコードを書く

F7 キーを押してコードエディタを開き、次のコードを追加します。

プロパティの公開

フォームから使うために、Title と Text プロパティを公開します。

public string Title { get => lblTitle.Text; set => lblTitle.Text = value; } public new string Text { get => txtValue.Text; set => txtValue.Text = value; }

UserControl は Control を継承しており、Control にはすでに Text プロパティがあります。

// Control クラス(基底クラス)には既に Text がある

public virtual string Text { get; set; }

ClearableTextBox で、内部の txtValue.Text を外に出すために同じ名前の Text を定義すると、基底クラスの Text を隠すことになります。

その「意図的に隠している」ことをコンパイラに伝えるために new を付けます。


new を付けない場合

new を付けないと、次のような警告が出ます。

CS0108: 'ClearableTextBox.Text’ は継承されたメンバー 'Control.Text’ を非表示にしています。

意図的に非表示にする場合は、new キーワードを使用してください。


同じく new が必要なイベント

TextChanged イベントも、基底クラス Control に既に定義されているため、同様に new が必要です。

public new event EventHandler TextChanged { add => txtValue.TextChanged += value; remove => txtValue.TextChanged -= value; }

まとめ

キーワード役割
new継承されたメンバーを意図的に隠すことを示す
override仮想メンバーを上書きする(Text は virtual だが、内部の TextBox に委譲したいため override は使わない)

override ではなく new を使うのは、基底の Text を上書きするのではなく、「この UserControl の Text は内部の TextBox の Text を指す」という別の意味を持たせたいためです。

イベントの転送

テキストが変わったことをフォームに伝えるため、TextChanged イベントを転送します。

public new event EventHandler TextChanged { add => txtValue.TextChanged += value; remove => txtValue.TextChanged -= value; }

クリアボタンの処理

btnClear をダブルクリックして Click イベントを作成し、次のコードを書きます。

private void btnClear_Click(object sender, EventArgs e) => Text = "";

ビルドしてツールボックスに表示する

ビルド → ソリューションのビルド を実行します。エラーがなければ、ツールボックスの下部に ClearableTextBox が表示されます。


フォームに UserControl を配置する

Form1 のデザイナーを開き、ツールボックスから ClearableTextBox を2つドラッグして配置します。

コントロール名前LocationTitle
ClearableTextBoxctlFirstName12, 12First Name
ClearableTextBoxctlLastName12, 71Last Name
LabellblFullName12, 252(空欄)

ctlFirstName と ctlLastName の Title プロパティは、プロパティウィンドウで「First Name」「Last Name」に設定します。


イベントを登録する

  1. ctlFirstName をダブルクリック → ctlFirstName_TextChanged が作成される
  2. ctlLastName をダブルクリック → ctlLastName_TextChanged が作成される
  3. フォームのタイトルバーをダブルクリック → Form1_Load が作成される

完成コード

ClearableTextBox.cs(UserControl 側)

using System; using System.Windows.Forms; namespace UserControlDemo { public partial class ClearableTextBox : UserControl { public ClearableTextBox() { InitializeComponent(); } public string Title { get => lblTitle.Text; set => lblTitle.Text = value; } public new string Text { get => txtValue.Text; set => txtValue.Text = value; } public new event EventHandler TextChanged { add => txtValue.TextChanged += value; remove => txtValue.TextChanged -= value; } private void btnClear_Click(object sender, EventArgs e) => Text = ""; } }

Form1.cs(フォーム側)

using System; using System.Windows.Forms; namespace UserControlDemo { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void UpdateNameLabel() { if (string.IsNullOrWhiteSpace(ctlFirstName.Text) || string.IsNullOrWhiteSpace(ctlLastName.Text)) lblFullName.Text = "姓と名の両方を入力してください。"; else lblFullName.Text = $"Hello {ctlFirstName.Text} {ctlLastName.Text}"; } private void ctlFirstName_TextChanged(object sender, EventArgs e) => UpdateNameLabel(); private void ctlLastName_TextChanged(object sender, EventArgs e) => UpdateNameLabel(); private void Form1_Load(object sender, EventArgs e) => UpdateNameLabel(); } }

プログラムの流れ

姓 or 名のテキストが変わる ↓ TextChanged が発生 ↓ UpdateNameLabel() が呼ばれる ↓ lblFullName.Text を更新

重要ポイント

UserControl は「複数コントロールを1つにまとめた部品」 です。

  • プロパティの公開 … フォームから内部コントロールにアクセスできるようにする(Title、Text など)
  • イベントの転送 … 内部コントロールのイベントをフォームに伝える(TextChanged など)
  • 論理動作 … 内部でボタンクリック時の処理を実装する(クリアなど)
  • ビルド するとツールボックスに表示され、他のフォームでも再利用できる
  • チーム開発では「Aさんが UserControl、Bさんがフォーム」と役割分担しやすい

発展:電話帳アプリで使う

WinFormsで作る電話帳アプリ(Listで管理する版) では、1件分の表示を Label や TextBox で作っています。これを UserControl にまとめると、1件分のレイアウトを1つの部品として再利用できます。


発展:チーム開発で役割分担する

WinFormsで2人開発を体験する では、フォームとリストを分担して作ります。UserControl を導入すると、「Aさんが ClearableTextBox を作る」「Bさんがフォームに配置する」という役割分担がしやすくなります。


発展アイデア

UserControl を使うと次のようなものも作れます。

  • 住所入力欄(郵便番号+住所+電話番号を1つにまとめる)
  • 検索ボックス(TextBox+検索ボタン)
  • 数値入力欄(Label+NumericUpDown+単位表示)
  • 日付選択欄(Label+DateTimePicker)

UserControl は部品化・再利用の基本です。入門シリーズの締めとして押さえておくと、実務アプリやチーム開発に進みやすくなります。

C# WinForms 入門シリーズの目次へ戻る

訪問数 104 回, 今日の訪問数 1回

広告