学習記事一覧 · WinForms基礎

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

これまでの学習では、

  • フォームに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 のデザイン画面に、次のコントロールを配置します。

コントロール 名前 プロパティ
Label lblTitle Location: 3, 5
TextBox txtValue Location: 3, 23、Size: 148, 23、Anchor: Top, Left, Right
Button btnClear Location: 157, 23、Size: 31, 23、Text: ↻、Anchor: Top, Right

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

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


UserControl のコードを書く

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

プロパティの公開

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

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

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

イベントの転送

テキストが変わったことをフォームに伝えるため、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つドラッグして配置します。

コントロール 名前 Location Title
ClearableTextBox ctlFirstName 12, 12 First Name
ClearableTextBox ctlLastName 12, 71 Last Name
Label lblFullName 12, 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 は部品化・再利用の基本です。入門シリーズの締めとして押さえておくと、実務アプリやチーム開発に進みやすくなります。