C#のWindowsフォームアプリケーション開発において、限られた画面スペースを有効活用するために欠かせないのが「TabControl(タブコントロール)」です。
設定画面やブラウザのように、カテゴリごとにページを切り替えて表示するUIは、ユーザーにとっても馴染み深く使いやすいものです。
この記事では、TabControlの基本的な使い方から、イベント処理、そして検索ニーズの高い「デザインのカスタマイズ」や「タブの非表示化」といった応用テクニックまで、実務で役立つノウハウを徹底解説します。
![]() 執筆者:マヒロ |
|
TabControl(タブコントロール)の基本実装
まずは、Visual StudioのツールボックスからTabControlを配置し、基本的な操作を行う方法を見ていきましょう。
フォームデザイナーでの操作だけでなく、コードから動的にタブを操作する方法も知っておくと、アプリケーションの柔軟性が高まります。
フォームへの配置とタブページの追加・削除
TabControlは、その中に複数の「TabPage(タブページ)」を持つコンテナコントロールです。
デザイナー上で「タブの追加」を行うこともできますが、動的にタブを増減させる場合は以下のようにコードを記述します。
using System;
using System.Windows.Forms;
namespace TabControlSample
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
// フォームロード時に初期化などを行う
InitializeTabs();
}
private void InitializeTabs()
{
// 描画パフォーマンス向上のためレイアウトロジックを一時停止
this.SuspendLayout();
// 新しいタブページを作成
TabPage newPage = new TabPage("新規タブ");
newPage.Name = "tabPageNew"; // 名前を付けておくと後で検索しやすい
// ボタンなどのコントロールをタブページに追加
// ★ポイント:フォームではなくTabPageに対してAddする
Button btn = new Button();
btn.Text = "ボタン";
btn.Location = new System.Drawing.Point(10, 10);
newPage.Controls.Add(btn);
// TabControlにタブページを追加
tabControl1.TabPages.Add(newPage);
// レイアウトロジックを再開
this.ResumeLayout();
}
private void RemoveTab()
{
// 名前を指定して削除(推奨)
// インデックス指定(RemoveAt)は、意図しないタブを消すリスクがあるため注意が必要です
if (tabControl1.TabPages.ContainsKey("tabPageNew"))
{
TabPage targetPage = tabControl1.TabPages["tabPageNew"];
tabControl1.TabPages.Remove(targetPage);
}
}
}
}
このソースコードでは、TabPage クラスのインスタンスを作成し、それを TabControl.TabPages コレクションに追加(Add)することでタブを増やしています。
逆に削除する場合は Remove メソッドを使用します。
重要なのは、タブの中身(ボタンやテキストボックス)はTabPageコントロールの上に配置するという点です。
フォームに直接置くのではなく、必ず newPage.Controls.Add(btn) のようにタブページに対してコントロールを追加してください。
また、大量のコントロールを配置する場合は、SuspendLayout() と ResumeLayout() を挟むことで、追加時の描画チラつきを抑えることができます。
選択されているタブを取得・変更する方法
ユーザーが現在どのタブを見ているかを取得したり、プログラム側から特定のタブに切り替えたりするには、SelectedIndex または SelectedTab プロパティを使用します。
// インデックス(番号)で指定して切り替え
tabControl1.SelectedIndex = 1; // 2番目のタブを選択(0始まり)
// TabPageオブジェクトを直接指定して切り替え
tabControl1.SelectedTab = tabPage2;
// 現在選択されているタブの情報を取得
string currentTabName = tabControl1.SelectedTab.Text;
int currentIndex = tabControl1.SelectedIndex;
MessageBox.Show($"現在は「{currentTabName}」が選択されています。");
画面遷移や入力チェックのエラー時に、該当するタブを強制的に表示させたい場合などに利用します。
タブ切り替え時のイベント処理
タブが切り替わったタイミングでデータを読み込んだり、画面表示を更新したりしたい場合は、イベントを利用します。
また、特定の条件下でタブの切り替えを「禁止」したい場合も、イベントハンドラで制御します。
SelectedIndexChangedイベントの使い方
タブの切り替えが完了した後に処理を行いたい場合は、SelectedIndexChanged イベントを使います。
これが最も一般的なイベントです。
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
// 選択されたタブを取得
TabControl tabCtrl = sender as TabControl;
TabPage current = tabCtrl.SelectedTab;
// タブごとの処理分岐
if (current != null && current.Name == "tabPageSettings")
{
Console.WriteLine("設定タブが開かれました。設定値をロードします。");
// 設定読み込み処理などをここに記述
}
}
このコードは、タブが切り替わるたびに実行されます。
sender を TabControl にキャストすることで、どのタブコントロールでイベントが発生したかを特定し、現在選択されているタブページ (SelectedTab) に応じて処理を分岐させています。
無駄な処理を減らすため、必要なタブが開かれた時だけ重い処理(DB接続など)を実行するといった使い方が効果的です。
選択変更をキャンセルするテクニック
「編集中のデータが保存されていない場合、タブの切り替えを許可したくない」といったケースでは、Selecting または Deselecting イベントを使用します。
これにより、切り替え処理を中断(キャンセル)させることができます。
private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
// 例えば、データが未保存かどうかをチェックするフラグ
bool isDataDirty = true;
// 特定の条件で切り替えをキャンセル
// e.TabPageは「移動先」のタブを指します
if (isDataDirty && e.TabPage.Name != "tabPageEdit")
{
DialogResult result = MessageBox.Show(
"保存されていないデータがあります。移動しますか?",
"確認",
MessageBoxButtons.YesNo
);
if (result == DialogResult.No)
{
// タブの切り替えをキャンセルする
e.Cancel = true;
}
}
}
TabControlCancelEventArgs の Cancel プロパティを true に設定することで、タブの移動を阻止できます。
ユーザーの誤操作によるデータ損失を防ぐために非常に重要なテクニックです。
タブのデザインや色を変更する方法(オーナードロー)
標準のWindowsフォームのTabControlは、プロパティで「タブの背景色」や「文字色」を簡単に変更することができません。
デザインをカスタマイズするには、「オーナードロー(OwnerDraw)」という手法を使い、描画処理を自分で記述する必要があります。
DrawModeプロパティとDrawItemイベント
まず、TabControlの DrawMode プロパティを TabDrawMode.OwnerDrawFixed に設定します。
これで、タブの描画がデフォルトのOS任せから、プログラマの制御下(DrawItem イベント)に移ります。
背景色や文字色を自由にカスタマイズするコード例
public MainForm()
{
InitializeComponent();
// オーナードローを有効にする
tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
// タブを描画するイベントを登録
tabControl1.DrawItem += tabControl1_DrawItem;
}
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
// 対象のタブコントロールとタブページを取得
TabControl tabCtrl = (TabControl)sender;
TabPage page = tabCtrl.TabPages[e.Index];
// 描画領域(タブの矩形)を取得
Rectangle bounds = e.Bounds;
// ブラシの準備(背景色と文字色)
Brush backBrush;
Brush foreBrush;
// 選択されているタブかどうかで色を変える
if (e.Index == tabCtrl.SelectedIndex)
{
// 選択時:青背景に白文字
backBrush = new SolidBrush(Color.DodgerBlue);
foreBrush = new SolidBrush(Color.White);
}
else
{
// 非選択時:グレー背景に黒文字
backBrush = new SolidBrush(Color.LightGray);
foreBrush = new SolidBrush(Color.Black);
}
// 1. 背景を塗りつぶす
e.Graphics.FillRectangle(backBrush, bounds);
// 2. 文字を描画する
// 文字列の配置(上下左右中央揃え)
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
e.Graphics.DrawString(
page.Text,
tabCtrl.Font,
foreBrush,
bounds,
stringFormat
);
// リソースの解放
backBrush.Dispose();
foreBrush.Dispose();
}
このコードを実行すると、選択されているタブが青色、それ以外がグレーで表示されるようになります。
e.Graphics オブジェクトを使って、四角形(背景)を塗りつぶし、その上に文字を描画しています。
特定のタブを非表示にする・隠すテクニック
TabControlには、各TabPageの Visible プロパティを false にしても、タブ(つまみ部分)自体は消えないという仕様があります。
特定のタブをユーザーから見えなくするには、TabControlの TabPages コレクションからそのページを一時的に削除(Remove)する必要があります。
TabPages.Removeによる非表示と再表示
タブを非表示にする(削除する)と、そのタブページへの参照や「元の位置」を見失ってしまう可能性があります。
そのため、非表示にする前に Dictionary などを使って情報を保持しておくことが重要です。
using System.Collections.Generic;
// タブとその元のインデックスを保持する辞書
private Dictionary<TabPage, int> hiddenTabs = new Dictionary<TabPage, int>();
// タブを非表示にするメソッド
private void HideTab(TabPage page)
{
// すでにTabControlにある場合のみ処理
if (tabControl1.TabPages.Contains(page))
{
// 現在のインデックスを保存してから削除
int index = tabControl1.TabPages.IndexOf(page);
// 辞書に保存(既に隠されている場合は更新しない)
if (!hiddenTabs.ContainsKey(page))
{
hiddenTabs[page] = index;
}
tabControl1.TabPages.Remove(page);
}
}
// タブを再表示するメソッド
private void ShowTab(TabPage page)
{
// 退避辞書に含まれている場合のみ処理
if (hiddenTabs.ContainsKey(page))
{
int originalIndex = hiddenTabs[page];
// 元のインデックスが現在のタブ数を超えないように調整(安全策)
// ※他のタブが削除されている可能性があるため
if (originalIndex > tabControl1.TabCount)
{
originalIndex = tabControl1.TabCount;
}
// 指定位置に挿入
tabControl1.TabPages.Insert(originalIndex, page);
// 辞書から削除
hiddenTabs.Remove(page);
}
}
このロジックを使用することで、見た目上「タブの表示・非表示」を切り替えることができます。
「管理者権限があるユーザーにだけ設定タブを表示する」といった機能を実装する際に非常に役立ちます。
削除前にインデックスを記録し、Insert メソッドを使って復帰させることで、元の順番を保ったまま再表示が可能です。
C#のスキルを活かして年収を上げる方法
以上、C#でのTabControlの使い方やデザインカスタマイズなどについて解説してきました。
なお、C#のスキルがある場合には、「転職して年収をアップさせる」「副業で稼ぐ」といった方法を検討するのがおすすめです。
業務システム開発やアプリ開発、ゲーム開発において需要の高いC#を扱えるエンジニアは、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。
なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。
併せて、副業案件を獲得できるエージェントにも登録しておくと、空いている時間を活かして稼げるようなC#の案件を探しやすくなります。
転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。



