C#ユーザーコントロールの作り方を初心者向けに解説|追加・配置・イベント実装までわかる入門ガイド

はじめに

C#でWindowsフォームアプリを作っていると、「同じ入力欄を複数の画面で使いたい」「ラベル・テキストボックス・ボタンをまとめて1つの部品にしたい」と感じることがあります。

そのようなときに便利なのが、C#ユーザーコントロールです。

ユーザーコントロールを使うと、複数の標準コントロールを組み合わせて、再利用しやすい独自の画面部品を作成できます。たとえば、検索ボックス、入力フォーム、一覧の1行分の表示、ログイン入力欄などを1つの部品としてまとめられます。

この記事では、C#初心者向けに、Windows Formsのユーザーコントロールの作り方をわかりやすく解説します。ユーザーコントロールの追加、フォームへの配置、プロパティの作成、イベント実装、完成コードまで順番に確認していきましょう。

1. C#ユーザーコントロールとは?初心者が最初に知るべき基本

C#ユーザーコントロールとは、複数のコントロールをまとめて作る「自作の部品」のようなものです。

Windows Formsでは、Label、TextBox、Button、ComboBoxなどの標準コントロールをフォームに配置して画面を作ります。ユーザーコントロールを使うと、それらを1つのまとまりとして扱えるようになります。

MicrosoftのWindows Forms公式ドキュメントでも、UserControlは複数の場所で再利用できるコントロールを作るための仕組みとして説明されています。

1-1. ユーザーコントロールの役割とできること

ユーザーコントロールの主な役割は、よく使う画面部品をまとめて再利用できるようにすることです。

たとえば、次のような部品を作れます。

・名前入力欄
・検索ボックス
・住所入力フォーム
・ログインフォームの一部
・画像と説明文をセットにした表示部品
・一覧画面の1行分の部品
・OKボタンとキャンセルボタンをまとめた操作部品

通常であれば、フォームごとにLabel、TextBox、Buttonなどを何度も配置する必要があります。しかしユーザーコントロールにまとめておけば、フォームにはその部品を1つ配置するだけで済みます。

また、見た目だけでなく、クリック時の処理、入力チェック、値の取得などもユーザーコントロール内に書けます。

1-2. フォーム・標準コントロール・ユーザーコントロールの違い

C#初心者が混乱しやすいのが、フォーム、標準コントロール、ユーザーコントロールの違いです。

フォームは、アプリケーションの画面そのものです。Windowsアプリで表示されるウィンドウにあたります。

標準コントロールは、Label、TextBox、Buttonなど、Visual Studioが最初から用意している部品です。

ユーザーコントロールは、標準コントロールを組み合わせて作る自作部品です。

たとえば、フォームが「机」だとすると、標準コントロールは「ペン」「ノート」「電卓」のような個別の道具です。ユーザーコントロールは、それらをまとめた「作業セット」のようなイメージです。

1-3. ユーザーコントロールを使うメリット

ユーザーコントロールを使うメリットはたくさんあります。

まず、同じ画面部品を何度も作らなくてよくなることです。複数のフォームで同じ入力欄を使いたい場合、ユーザーコントロールにしておけば、フォームごとに同じ配置や処理を書く必要がありません。

次に、修正が楽になることです。たとえば、共通の検索ボックスのデザインを変更したい場合、ユーザーコントロールを1か所修正すれば、その部品を使っている画面に反映できます。

さらに、フォームのコードが整理されることも大きなメリットです。フォームにすべての処理を書くと、コードが長くなって読みにくくなります。ユーザーコントロールに処理を分けることで、フォーム側は画面全体の制御に集中できます。

1-4. ユーザーコントロールが向いているケース・向いていないケース

ユーザーコントロールが向いているのは、次のようなケースです。

・複数のフォームで同じ部品を使う
・Label、TextBox、Buttonなどをセットで扱いたい
・入力チェックを部品側にまとめたい
・画面を機能ごとに分割したい
・フォームのコードをすっきりさせたい

一方で、ユーザーコントロールが向いていないケースもあります。

たとえば、1回しか使わない単純なLabelやButtonをわざわざユーザーコントロールにする必要はありません。また、フォーム全体の画面遷移やアプリ全体の処理をユーザーコントロールに詰め込みすぎると、かえって管理しにくくなります。

ユーザーコントロールは、あくまで「再利用できる画面部品」として使うのが基本です。

1-5. WinFormsとWPFでのユーザーコントロールの違い

C#には、Windows FormsだけでなくWPFにもユーザーコントロールがあります。

Windows Formsのユーザーコントロールは、Label、TextBox、Buttonなどをデザイナー上で配置して作ることが多く、初心者でも直感的に扱いやすいのが特徴です。

WPFのユーザーコントロールは、XAMLで画面を定義し、コードビハインドで処理を書く形が一般的です。WPFではスタイル、テンプレート、バインディングなどを使えるため、見た目やデータ連携をより柔軟に設計できます。WPFでもUserControlから派生して既存の部品を組み合わせる方法が基本として紹介されています。

この記事では、初心者が学びやすいWindows FormsのC#ユーザーコントロールを中心に解説します。

2. C#ユーザーコントロール作成前に準備するもの

C#ユーザーコントロールを作成する前に、まずは開発環境とプロジェクトを準備しましょう。

2-1. Visual Studioで必要な開発環境

C#でWindows Formsアプリを作るには、Visual Studioを使用するのが一般的です。

必要な環境は次のとおりです。

・Visual Studio
・.NETデスクトップ開発ワークロード
・C#
・Windows Forms Appのプロジェクト

Visual Studioのインストール時に「.NET デスクトップ開発」を選択しておくと、Windows Formsアプリケーションを作成できます。

Windows Formsは、.NETでWindows向けのGUIアプリケーションを作るための仕組みです。Microsoftの公式ドキュメントでも、Windows Formsは.NET上で利用できるWindows向けのグラフィカルユーザーインターフェイスとして説明されています。

2-2. Windowsフォームアプリケーションのプロジェクトを作成する

Visual Studioを起動したら、まずWindows Formsアプリケーションを作成します。

手順は次のとおりです。

  1. Visual Studioを起動する

  2. 「新しいプロジェクトの作成」を選択する

  3. 「Windows Forms App」または「Windows フォーム アプリ」を選択する

  4. 言語がC#になっていることを確認する

  5. プロジェクト名を入力する

  6. 作成ボタンをクリックする

初心者の場合は、まず通常のWindows Forms Appプロジェクトを作り、その中にユーザーコントロールを追加する方法がおすすめです。

2-3. 作成するサンプルユーザーコントロールの完成イメージ

この記事では、次のようなシンプルな入力欄付きユーザーコントロールを作成します。

・ラベルを表示する
・テキストボックスに文字を入力できる
・ボタンをクリックするとフォーム側に通知する
・フォーム側で入力された値を受け取る

完成イメージは、次のような部品です。

[名前を入力してください]  [              ]  [送信]

この部品をユーザーコントロールとして作成し、メインフォームに配置します。

2-4. 初心者がつまずきやすいプロジェクト種類の選び方

Visual Studioには似たようなテンプレートが複数あります。

初心者がC#ユーザーコントロールを学ぶ場合は、まず次のように選ぶとわかりやすいです。

・画面アプリを作りたい場合:Windows Forms App
・部品だけを別DLLとして作りたい場合:Windows Forms Control Library
・WPFで作りたい場合:WPF AppまたはWPF User Control Library

最初からControl Libraryを選ぶと、フォームに配置して動作確認する流れが少しわかりにくい場合があります。そのため、入門ではWindows Forms Appを作成し、その中にユーザーコントロールを追加する方法がおすすめです。

3. C#ユーザーコントロールの作り方

ここからは、実際にC#ユーザーコントロールを作成していきます。

3-1. プロジェクトにユーザーコントロールを追加する手順

Windows Formsプロジェクトを作成したら、次の手順でユーザーコントロールを追加します。

  1. ソリューションエクスプローラーでプロジェクトを右クリックする

  2. 「追加」を選択する

  3. 「ユーザーコントロール」を選択する

  4. 名前を入力する

  5. 「追加」をクリックする

MicrosoftのWindows Formsユーザーコントロール概要でも、Visual Studioでプロジェクトを右クリックし、「追加」からUser Controlを作成する流れが紹介されています。

3-2. ユーザーコントロールの名前を変更する

ユーザーコントロールの名前は、あとから見ても役割がわかる名前にしましょう。

たとえば、入力欄付きのユーザーコントロールなら次のような名前が考えられます。

C#
InputUserControl
NameInputControl
SearchBoxControl
CustomerInputControl

今回は、InputUserControlという名前で作成します。

ファイル名は次のようになります。

InputUserControl.cs
InputUserControl.Designer.cs

InputUserControl.csには主に自分で書く処理を記述します。
InputUserControl.Designer.csには、デザイナーで配置したコントロールの情報が自動生成されます。

通常、初心者はDesigner.csを直接編集しないようにしましょう。

3-3. デザイナー画面でラベル・テキストボックス・ボタンを配置する

ユーザーコントロールを追加すると、フォームと同じようなデザイナー画面が開きます。

そこに、ツールボックスから次のコントロールを配置します。

・Label
・TextBox
・Button

配置したら、それぞれの名前をわかりやすく変更します。

Label    → labelTitle
TextBox → textBoxInput
Button → buttonSubmit

コントロール名は、後からコードで使います。label1button1のままでも動きますが、数が増えるとわかりにくくなるため、意味のある名前に変更するのがおすすめです。

3-4. プロパティからサイズ・文字・配置を調整する

デザイナーでコントロールを選択すると、プロパティウィンドウから文字やサイズを変更できます。

たとえば、次のように設定します。

labelTitle.Text      = 名前
textBoxInput.Width = 150
buttonSubmit.Text = 送信

ユーザーコントロール自体のサイズも調整します。

InputUserControl.Size = 350, 40

フォームに配置しやすいように、必要最小限のサイズにしておくと扱いやすくなります。

3-5. ユーザーコントロール内に処理を書く基本

ユーザーコントロールは、フォームと同じようにC#コードを書けます。

たとえば、ボタンをダブルクリックすると、クリックイベントが自動で作成されます。

C#
private void buttonSubmit_Click(object sender, EventArgs e)
{
MessageBox.Show(textBoxInput.Text);
}

このように書くと、ユーザーコントロール内のボタンをクリックしたときに、テキストボックスの内容を表示できます。

ただし、実際のアプリではユーザーコントロール内だけで処理を完結させるのではなく、フォーム側にイベントで通知する設計にすると再利用しやすくなります。

4. 作成したユーザーコントロールをフォームに配置する方法

作成したC#ユーザーコントロールは、通常のButtonやTextBoxと同じようにフォームへ配置できます。

4-1. ツールボックスからフォームへドラッグ&ドロップする

ユーザーコントロールを作成してビルドすると、ツールボックスに作成したコントロールが表示されることがあります。

表示されたら、通常のコントロールと同じようにフォームへドラッグ&ドロップします。

手順は次のとおりです。

  1. プロジェクトをビルドする

  2. Form1.csのデザイナーを開く

  3. ツールボックスを開く

  4. 作成したユーザーコントロールを探す

  5. フォームへドラッグ&ドロップする

配置すると、フォーム上に自作のユーザーコントロールが表示されます。

4-2. ツールボックスに表示されないときの確認ポイント

ユーザーコントロールがツールボックスに表示されない場合は、次の点を確認してください。

・プロジェクトをビルドしたか
・ユーザーコントロールのクラスがpublicになっているか
・UserControlを継承しているか
・デザイナーにエラーが出ていないか
・Visual Studioを再起動してみたか

クラス定義は、基本的に次のようになります。

C#
public partial class InputUserControl : UserControl
{
public InputUserControl()
{
InitializeComponent();
}
}

publicが付いていない場合、外部から使えないことがあります。ツールボックスに表示されないときは、まずビルドとクラス定義を確認しましょう。

4-3. コードでユーザーコントロールを追加する方法

ユーザーコントロールは、デザイナーだけでなくコードから追加することもできます。

Form1.csに次のように書きます。

C#
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

InputUserControl inputControl = new InputUserControl();
inputControl.Location = new Point(20, 20);

this.Controls.Add(inputControl);
}
}

このコードでは、InputUserControlのインスタンスを作成し、フォームのControlsコレクションに追加しています。

4-4. Location・Size・Dock・Anchorで配置を調整する

ユーザーコントロールの配置は、通常のコントロールと同じように調整できます。

Locationは表示位置を指定します。

C#
inputControl.Location = new Point(20, 20);

Sizeは大きさを指定します。

C#
inputControl.Size = new Size(350, 40);

Dockは親コントロールに対して、どのようにくっつけるかを指定します。

C#
inputControl.Dock = DockStyle.Top;

Anchorはフォームのサイズ変更時に、どの端に固定するかを指定します。

C#
inputControl.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;

フォームのサイズ変更に対応したい場合は、DockAnchorをうまく使いましょう。

4-5. 複数のフォームで同じユーザーコントロールを再利用する

ユーザーコントロールの大きなメリットは、複数のフォームで再利用できることです。

たとえば、InputUserControlをForm1、Form2、Form3で使いたい場合、それぞれのフォームに配置するだけで同じ部品を使えます。

同じ入力欄をフォームごとに作る必要がなくなるため、画面の統一感を保ちやすくなります。また、ユーザーコントロール側のデザインや処理を修正すれば、使っているフォームにも反映できます。

5. ユーザーコントロールにプロパティを追加する方法

ユーザーコントロールを実用的に使うには、フォーム側から値を渡したり、ユーザーコントロール内の値を取得したりできるようにする必要があります。

そのために使うのが、publicプロパティです。

5-1. フォーム側から値を渡せるようにする考え方

ユーザーコントロール内のLabelやTextBoxを、フォーム側から直接操作する設計はおすすめしません。

たとえば、フォーム側で次のように内部のTextBoxを直接操作する形です。

C#
inputUserControl1.textBoxInput.Text = "山田";

これは、ユーザーコントロールの内部構造にフォーム側が依存してしまうため、後から変更しにくくなります。

代わりに、ユーザーコントロール側でpublicプロパティを用意します。

C#
inputUserControl1.InputText = "山田";

このようにすると、フォーム側はユーザーコントロールの内部にTextBoxがあるかどうかを意識しなくて済みます。

5-2. publicプロパティを作成する基本コード

ユーザーコントロールにプロパティを追加する基本コードは次のとおりです。

C#
public string InputText
{
get
{
return textBoxInput.Text;
}
set
{
textBoxInput.Text = value;
}
}

このプロパティを作ると、フォーム側から次のように値を設定できます。

C#
inputUserControl1.InputText = "初期値";

値を取得する場合は、次のように書きます。

C#
string text = inputUserControl1.InputText;

5-3. ラベルやテキストボックスの値を外部から変更する

ラベルの文字も外部から変更できるようにするには、次のようなプロパティを作成します。

C#
public string LabelText
{
get
{
return labelTitle.Text;
}
set
{
labelTitle.Text = value;
}
}

フォーム側では、次のように使えます。

C#
inputUserControl1.LabelText = "名前";
inputUserControl1.InputText = "佐藤";

これで、同じユーザーコントロールを使いながら、フォームごとに表示内容を変えられます。

たとえば、別のフォームでは次のように使えます。

C#
inputUserControl1.LabelText = "メールアドレス";

同じ部品でも、ラベルの文字を変えるだけで別の入力欄として再利用できます。

5-4. プロパティウィンドウに表示させる方法

作成したプロパティは、属性を付けることでVisual Studioのプロパティウィンドウに表示しやすくできます。

C#
using System.ComponentModel;

[Category("表示")]
[Description("ラベルに表示する文字を設定します。")]
public string LabelText
{
get
{
return labelTitle.Text;
}
set
{
labelTitle.Text = value;
}
}

Categoryはプロパティウィンドウでの分類名です。
Descriptionはプロパティの説明文です。

これを付けておくと、デザイナー上でユーザーコントロールを選択したときに、独自プロパティを見つけやすくなります。

5-5. 値が反映されないときの原因と対処法

プロパティを作成したのに値が反映されない場合は、次の原因が考えられます。

まず、プロパティのsetで内部コントロールに値を設定していない可能性があります。

C#
public string LabelText
{
get { return labelTitle.Text; }
set { labelTitle.Text = value; }
}

このように、setの中でlabelTitle.Text = value;と書く必要があります。

次に、InitializeComponent()より前に値を設定している場合も注意が必要です。通常、コンストラクターでは先にInitializeComponent()を呼び出します。

C#
public InputUserControl()
{
InitializeComponent();

LabelText = "名前";
}

また、デザイナー上で値を変更しても反映されない場合は、一度ビルドし直す、フォームを閉じて再度開く、Visual Studioを再起動するなども試してみましょう。

6. ユーザーコントロールにイベントを実装する方法

ユーザーコントロールでは、内部のボタンがクリックされたことをフォーム側に通知できます。

このときに使うのが、イベントです。

6-1. ユーザーコントロール内のボタンクリックイベントを作成する

まず、ユーザーコントロール上のボタンをダブルクリックして、クリックイベントを作成します。

C#
private void buttonSubmit_Click(object sender, EventArgs e)
{
MessageBox.Show("ボタンがクリックされました。");
}

これで、ユーザーコントロール内のボタンがクリックされたときに処理を実行できます。

ただし、このままだと処理がユーザーコントロール内で完結しています。フォーム側で入力値を受け取りたい場合は、イベントを使って通知します。

6-2. フォーム側でイベントを受け取る考え方

ユーザーコントロールは、部品として独立している方が再利用しやすくなります。

そのため、ユーザーコントロール側では「ボタンが押された」という事実だけを通知し、実際に何をするかはフォーム側で決める設計にします。

たとえば、ユーザーコントロール側は次のように通知します。

C#
Submitted?.Invoke(this, EventArgs.Empty);

フォーム側では、次のように受け取ります。

C#
inputUserControl1.Submitted += InputUserControl1_Submitted;

このようにすると、同じユーザーコントロールでも、フォームごとに異なる処理を実装できます。

6-3. カスタムイベントを定義する基本コード

ユーザーコントロールにカスタムイベントを定義するには、次のように書きます。

C#
public event EventHandler Submitted;

そして、ボタンクリック時にイベントを発火します。

C#
private void buttonSubmit_Click(object sender, EventArgs e)
{
Submitted?.Invoke(this, EventArgs.Empty);
}

?.Invokeを使うと、イベントの受け取り先が登録されている場合だけ安全に実行できます。

6-4. EventHandlerを使ってイベントを通知する

EventHandlerは、C#でよく使われる標準的なイベントの型です。

ユーザーコントロール側のコード例は次のとおりです。

C#
public event EventHandler Submitted;

private void buttonSubmit_Click(object sender, EventArgs e)
{
Submitted?.Invoke(this, EventArgs.Empty);
}

フォーム側では、次のようにイベントを登録します。

C#
public Form1()
{
InitializeComponent();

inputUserControl1.Submitted += InputUserControl1_Submitted;
}

private void InputUserControl1_Submitted(object sender, EventArgs e)
{
MessageBox.Show("ユーザーコントロールのボタンが押されました。");
}

これで、ユーザーコントロール内のボタンがクリックされたときに、フォーム側の処理が実行されます。

6-5. イベント発火時に値を渡す方法

ボタンがクリックされたときに、テキストボックスの入力値もフォーム側へ渡したい場合は、独自のEventArgsクラスを作成します。

C#
public class InputSubmittedEventArgs : EventArgs
{
public string InputText { get; }

public InputSubmittedEventArgs(string inputText)
{
InputText = inputText;
}
}

ユーザーコントロール側では、次のようにイベントを定義します。

C#
public event EventHandler<InputSubmittedEventArgs> Submitted;

ボタンクリック時に入力値を渡します。

C#
private void buttonSubmit_Click(object sender, EventArgs e)
{
Submitted?.Invoke(this, new InputSubmittedEventArgs(textBoxInput.Text));
}

フォーム側では、次のように受け取ります。

C#
private void InputUserControl1_Submitted(object sender, InputSubmittedEventArgs e)
{
MessageBox.Show(e.InputText);
}

このようにすると、ユーザーコントロール内の入力値を安全にフォーム側へ渡せます。

6-6. イベントが動かないときの確認ポイント

イベントが動かない場合は、次の点を確認しましょう。

・ボタンのClickイベントが設定されているか
・イベントをフォーム側で登録しているか
・イベント名を間違えていないか
・ユーザーコントロールを配置した後に登録しているか
・別のインスタンスにイベントを登録していないか

特に多いのは、フォーム側でイベント登録を忘れているケースです。

C#
inputUserControl1.Submitted += InputUserControl1_Submitted;

この1行がないと、ユーザーコントロール側でイベントを発火してもフォーム側の処理は呼び出されません。

7. 実践サンプル:入力欄付きユーザーコントロールを作ってみよう

ここからは、実際に入力欄付きのC#ユーザーコントロールを作成します。

7-1. 今回作るサンプルの仕様

今回作るユーザーコントロールの仕様は次のとおりです。

・ラベルを表示する
・テキストボックスに入力できる
・送信ボタンを押せる
・フォーム側からラベル文字を変更できる
・フォーム側から入力値を取得できる
・ボタンクリック時にフォーム側へ入力値を通知する

シンプルですが、実務でもよく使う基本要素が含まれています。

7-2. ユーザーコントロールの画面を作成する

まず、InputUserControlを作成し、デザイナーで次の3つを配置します。

Label    : labelTitle
TextBox : textBoxInput
Button : buttonSubmit

各コントロールのプロパティは、次のように設定します。

labelTitle.Text    = 入力
buttonSubmit.Text = 送信

配置例は次のようなイメージです。

[入力] [             ] [送信]

7-3. 入力値を取得するプロパティを作成する

InputUserControl.csに、入力値を取得・設定するプロパティを追加します。

C#
public string InputText
{
get
{
return textBoxInput.Text;
}
set
{
textBoxInput.Text = value;
}
}

ラベル文字も外部から変更できるようにします。

C#
public string LabelText
{
get
{
return labelTitle.Text;
}
set
{
labelTitle.Text = value;
}
}

これで、フォーム側から次のように操作できます。

C#
inputUserControl1.LabelText = "名前";
inputUserControl1.InputText = "山田太郎";

7-4. ボタンクリック時にフォームへ通知する

まず、入力値を渡すためのイベント引数クラスを作成します。

C#
public class InputSubmittedEventArgs : EventArgs
{
public string InputText { get; }

public InputSubmittedEventArgs(string inputText)
{
InputText = inputText;
}
}

次に、ユーザーコントロール側でイベントを定義します。

C#
public event EventHandler<InputSubmittedEventArgs> Submitted;

ボタンクリック時にイベントを発火します。

C#
private void buttonSubmit_Click(object sender, EventArgs e)
{
Submitted?.Invoke(this, new InputSubmittedEventArgs(InputText));
}

これで、ボタンが押されたときにフォーム側へ入力値を通知できます。

7-5. メインフォーム側で入力値を表示する

Form1側では、ユーザーコントロールのイベントを登録します。

C#
public Form1()
{
InitializeComponent();

inputUserControl1.LabelText = "名前";
inputUserControl1.Submitted += InputUserControl1_Submitted;
}

イベントを受け取る処理を書きます。

C#
private void InputUserControl1_Submitted(object sender, InputSubmittedEventArgs e)
{
MessageBox.Show("入力された値:" + e.InputText);
}

これで、ユーザーコントロール内の送信ボタンをクリックすると、フォーム側で入力値を表示できます。

7-6. 完成コードの全体例

以下は、デザイナーでlabelTitletextBoxInputbuttonSubmitを配置済みの場合の完成コードです。

まず、InputSubmittedEventArgs.csを作成します。

C#
using System;

namespace UserControlSample
{
public class InputSubmittedEventArgs : EventArgs
{
public string InputText { get; }

public InputSubmittedEventArgs(string inputText)
{
InputText = inputText;
}
}
}

次に、InputUserControl.csです。

C#
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace UserControlSample
{
public partial class InputUserControl : UserControl
{
public event EventHandler<InputSubmittedEventArgs> Submitted;

public InputUserControl()
{
InitializeComponent();
}

[Category("表示")]
[Description("ラベルに表示する文字を設定します。")]
public string LabelText
{
get
{
return labelTitle.Text;
}
set
{
labelTitle.Text = value;
}
}

[Category("入力")]
[Description("テキストボックスの入力値を取得または設定します。")]
public string InputText
{
get
{
return textBoxInput.Text;
}
set
{
textBoxInput.Text = value;
}
}

private void buttonSubmit_Click(object sender, EventArgs e)
{
Submitted?.Invoke(this, new InputSubmittedEventArgs(InputText));
}
}
}

最後に、Form1.csです。

C#
using System;
using System.Windows.Forms;

namespace UserControlSample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

inputUserControl1.LabelText = "名前";
inputUserControl1.Submitted += InputUserControl1_Submitted;
}

private void InputUserControl1_Submitted(object sender, InputSubmittedEventArgs e)
{
MessageBox.Show("入力された値:" + e.InputText);
}
}
}

もしコードだけでユーザーコントロールを作成したい場合は、次のように書くこともできます。

C#
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace UserControlSample
{
public class CodeInputUserControl : UserControl
{
private Label labelTitle;
private TextBox textBoxInput;
private Button buttonSubmit;

public event EventHandler<InputSubmittedEventArgs> Submitted;

public CodeInputUserControl()
{
InitializeControls();
}

[Category("表示")]
[Description("ラベルに表示する文字を設定します。")]
public string LabelText
{
get
{
return labelTitle.Text;
}
set
{
labelTitle.Text = value;
}
}

[Category("入力")]
[Description("テキストボックスの入力値を取得または設定します。")]
public string InputText
{
get
{
return textBoxInput.Text;
}
set
{
textBoxInput.Text = value;
}
}

private void InitializeControls()
{
this.Size = new Size(350, 35);

labelTitle = new Label();
labelTitle.Text = "入力";
labelTitle.Location = new Point(0, 8);
labelTitle.AutoSize = true;

textBoxInput = new TextBox();
textBoxInput.Location = new Point(70, 5);
textBoxInput.Width = 170;

buttonSubmit = new Button();
buttonSubmit.Text = "送信";
buttonSubmit.Location = new Point(250, 3);
buttonSubmit.Width = 80;
buttonSubmit.Click += buttonSubmit_Click;

this.Controls.Add(labelTitle);
this.Controls.Add(textBoxInput);
this.Controls.Add(buttonSubmit);
}

private void buttonSubmit_Click(object sender, EventArgs e)
{
Submitted?.Invoke(this, new InputSubmittedEventArgs(InputText));
}
}
}

8. C#ユーザーコントロールでよくあるエラーと解決策

C#ユーザーコントロールを作成していると、初心者がつまずきやすいエラーがあります。ここでは代表的な原因と解決策を紹介します。

8-1. ツールボックスにユーザーコントロールが表示されない

ツールボックスに表示されない場合は、まずプロジェクトをビルドしてください。

ビルド → ソリューションのビルド

それでも表示されない場合は、次を確認します。

・クラスがpublicになっているか
・UserControlを継承しているか
・コンストラクターでエラーが発生していないか
・デザイナーが正常に開けるか
・プロジェクト内にビルドエラーがないか

また、Visual Studioのツールボックスを右クリックして「ツールボックスのリセット」を試す方法もあります。

8-2. フォームに配置するとエラーになる

フォームに配置した瞬間にエラーが出る場合、ユーザーコントロールのコンストラクター内で例外が発生している可能性があります。

特に注意したいのは、デザイン時にもコンストラクターが実行されることです。

たとえば、コンストラクターでファイル読み込みやデータベース接続を行うと、デザイナー上でエラーになることがあります。

必要であれば、デザイン時かどうかを判定します。

C#
if (!DesignMode)
{
// 実行時だけ行いたい処理を書く
}

ただし、DesignModeは状況によって期待どおりに判定できない場合もあるため、コンストラクターには重い処理を書かないのが基本です。

8-3. デザイナーが開けない

デザイナーが開けない場合は、InitializeComponent()周辺やコンストラクター内のコードに問題があることが多いです。

確認ポイントは次のとおりです。

InitializeComponent()を削除していないか
・コントロール名を変更したのにコード側が古い名前のままになっていないか
・コンストラクターで例外が発生していないか
・Designer.csを手動で壊していないか

初心者の場合、InputUserControl.Designer.csを直接編集してしまい、デザイナーが開けなくなることがあります。基本的には、Designer.csはVisual Studioに任せ、自分の処理は通常の.csファイルに書きましょう。

8-4. イベントが発火しない

イベントが発火しない場合は、まずボタンのClickイベントが正しく設定されているか確認します。

デザイナーでボタンを選択し、プロパティウィンドウのイベント欄でClickにメソッドが設定されているか確認しましょう。

また、フォーム側でカスタムイベントを登録しているかも確認します。

C#
inputUserControl1.Submitted += InputUserControl1_Submitted;

ユーザーコントロール側でイベントを定義しただけでは、フォーム側の処理は呼び出されません。必ずイベント登録が必要です。

8-5. プロパティの値が反映されない

プロパティの値が反映されない場合は、getsetの中身を確認しましょう。

正しい例は次のとおりです。

C#
public string LabelText
{
get
{
return labelTitle.Text;
}
set
{
labelTitle.Text = value;
}
}

間違った例として、内部コントロールに値を設定していないケースがあります。

C#
private string labelText;

public string LabelText
{
get
{
return labelText;
}
set
{
labelText = value;
}
}

このコードでは、labelText変数の値は変わりますが、labelTitle.Textは変わりません。画面に反映したい場合は、内部コントロールのプロパティも更新する必要があります。

8-6. ビルドしても変更内容が反映されない

変更内容が反映されない場合は、次を試してみましょう。

・ソリューションをリビルドする
・フォームのデザイナーを閉じて開き直す
・Visual Studioを再起動する
・binフォルダーとobjフォルダーを削除して再ビルドする
・同名の古いユーザーコントロールを参照していないか確認する

特に、ツールボックスに古い状態のユーザーコントロールが残っている場合があります。その場合は、ツールボックスのリセットや再ビルドが有効です。

9. ユーザーコントロールを使いやすくする設計のコツ

C#ユーザーコントロールは、作るだけなら簡単です。しかし、使いやすく保守しやすい部品にするには設計のコツがあります。

9-1. 1つのユーザーコントロールに機能を詰め込みすぎない

ユーザーコントロールに多くの機能を詰め込みすぎると、再利用しにくくなります。

たとえば、入力欄、一覧表示、保存処理、検索処理、画面遷移処理をすべて1つのユーザーコントロールに入れると、その部品は特定の画面でしか使えなくなります。

ユーザーコントロールは、できるだけ役割を絞るのが基本です。

良い例:名前入力用ユーザーコントロール
悪い例:顧客登録画面全体の処理をすべて持つユーザーコントロール

部品として再利用したいなら、1つのユーザーコントロールには1つの明確な役割を持たせましょう。

9-2. 名前の付け方をわかりやすくする

ユーザーコントロール名や内部コントロール名は、あとから読んでも意味がわかる名前にしましょう。

たとえば、次のような名前がおすすめです。

InputUserControl
SearchBoxControl
CustomerInfoControl
LoginInputControl

内部コントロールも、label1button1のままではなく、役割がわかる名前にします。

labelTitle
textBoxInput
buttonSubmit

名前がわかりやすいと、コードを読むときの負担が大きく減ります。

9-3. 外部から操作する部分はプロパティやイベントで公開する

ユーザーコントロールの内部コントロールを直接外部に公開するのは避けましょう。

フォーム側から操作したい値は、プロパティとして公開します。

C#
public string InputText
{
get { return textBoxInput.Text; }
set { textBoxInput.Text = value; }
}

ユーザーコントロール内で起きた操作は、イベントとして外部へ通知します。

C#
public event EventHandler Submitted;

このように、外部とのやり取りをプロパティとイベントに絞ることで、ユーザーコントロールの内部構造を変更しやすくなります。

9-4. フォーム側とユーザーコントロール側の責任を分ける

ユーザーコントロール側とフォーム側の責任を分けることも重要です。

ユーザーコントロール側の責任は、部品としての表示や入力操作です。

・ラベルを表示する
・入力値を保持する
・ボタンが押されたことを通知する

フォーム側の責任は、画面全体の制御です。

・入力値を使って保存する
・別画面を開く
・アプリ全体の処理を進める

ユーザーコントロールがデータベース保存や画面遷移まで直接行うと、再利用しにくくなります。ユーザーコントロールは「部品」、フォームは「画面全体の管理」と考えると設計しやすくなります。

9-5. 再利用しやすい部品として設計する

再利用しやすいユーザーコントロールにするには、特定のフォームに依存しすぎないことが大切です。

たとえば、ユーザーコントロール内で直接Form1を参照するのは避けましょう。

悪い例です。

C#
Form1 form = new Form1();
form.SomeMethod();

このようにすると、そのユーザーコントロールはForm1専用になってしまいます。

代わりに、イベントでフォーム側へ通知します。

C#
Submitted?.Invoke(this, EventArgs.Empty);

フォーム側で必要な処理を実行すれば、同じユーザーコントロールを別のフォームでも使えます。

10. C#ユーザーコントロールに関するよくある質問

ここでは、C#ユーザーコントロールに関する初心者向けのよくある質問に回答します。

10-1. ユーザーコントロールとカスタムコントロールの違いは?

ユーザーコントロールは、既存の標準コントロールを組み合わせて作る部品です。

たとえば、Label、TextBox、Buttonを組み合わせて、入力欄付きの部品を作る場合はユーザーコントロールが向いています。

一方、カスタムコントロールは、描画や動作をより細かく自分で制御するためのコントロールです。標準コントロールの組み合わせでは実現しにくい独自の見た目や動作を作りたい場合に使います。

初心者は、まずユーザーコントロールから学ぶのがおすすめです。

10-2. ユーザーコントロールは別プロジェクトでも使える?

使えます。

別プロジェクトでも使いたい場合は、Windows Forms Control Libraryとして作成し、DLLとして参照する方法があります。

ただし、初心者の場合は、まず同じWindows Forms Appプロジェクト内でユーザーコントロールを作成し、慣れてから別プロジェクト化すると理解しやすいです。

別プロジェクトにする場合は、参照設定、名前空間、ビルド順序などに注意しましょう。

10-3. WPFでも同じようにユーザーコントロールを作れる?

WPFでもユーザーコントロールを作れます。

ただし、Windows Formsとは作り方が少し違います。WPFでは、主にXAMLで画面を作成し、C#のコードビハインドで処理を書きます。

Windows Formsではデザイナー上にLabelやTextBoxを配置して作ることが多いですが、WPFではXAMLでレイアウト、バインディング、スタイルを定義することが一般的です。

考え方としては、どちらも「複数の部品をまとめて再利用できるようにする」という点では同じです。

10-4. コードだけでユーザーコントロールを作成できる?

できます。

デザイナーを使わず、C#コードだけでLabel、TextBox、Buttonを作成し、Controls.Addで追加すればユーザーコントロールを作成できます。

C#
Label label = new Label();
label.Text = "名前";
label.Location = new Point(0, 5);

TextBox textBox = new TextBox();
textBox.Location = new Point(60, 2);

this.Controls.Add(label);
this.Controls.Add(textBox);

ただし、初心者の場合はデザイナーを使った方が視覚的にわかりやすいです。慣れてきたら、コードだけで作る方法にも挑戦するとよいでしょう。

10-5. 初心者はユーザーコントロールをいつ使えばいい?

初心者は、次のような場面でユーザーコントロールを使うとよいです。

・同じ部品を2回以上作りそうなとき
・フォームの中がコントロールだらけになってきたとき
・入力欄とボタンをセットで扱いたいとき
・フォームのコードが長くなってきたとき
・画面を機能ごとに分けたいとき

最初から無理にユーザーコントロール化する必要はありません。まずフォームに普通に作ってみて、「これは別の画面でも使えそう」と感じたタイミングでユーザーコントロールに分けると理解しやすいです。

まとめ

C#ユーザーコントロールは、Windows Formsアプリで再利用できる画面部品を作るための便利な仕組みです。

Label、TextBox、Buttonなどの標準コントロールを組み合わせて1つの部品にできるため、複数のフォームで同じ部品を使いたい場合や、フォームのコードを整理したい場合に役立ちます。

基本の流れは次のとおりです。

  1. Windows Forms Appプロジェクトを作成する

  2. プロジェクトにユーザーコントロールを追加する

  3. デザイナーでLabel、TextBox、Buttonなどを配置する

  4. publicプロパティで外部から値を操作できるようにする

  5. イベントを使ってフォーム側へ通知する

  6. フォームに配置して再利用する

初心者がC#ユーザーコントロールを学ぶときは、まず小さな部品から作るのがおすすめです。入力欄付きユーザーコントロールや検索ボックスなど、シンプルなものから始めると、プロパティやイベントの使い方も自然に理解できます。

ユーザーコントロールを使いこなせるようになると、Windows Formsアプリの画面設計がかなり楽になります。同じコードを何度も書かずに済み、修正にも強いアプリを作れるようになります。