【C#入門】Controlとしてまとめて扱う|WinFormsのコントロールとforeach
前回は、Button を継承した MyButton を作りました。
MyButton は Button の一種であり、さらに Control の一種でもあります。
今回はこの関係を利用して、種類の異なるコントロールを Control 型としてまとめて扱う方法を学びます。
① Button・Label・TextBoxの共通点
フォームに置く次のコントロールは、見た目も役割も異なります。
Button:クリックできるLabel:文字を表示するTextBox:文字を入力できる
しかし、どれも Control を継承しています。
Control
├─ Button
├─ Label
└─ TextBox
そのため、Text、BackColor、ForeColor、Location など、Control に用意された共通機能を利用できます。
② 1つずつ設定した場合
フォームに button1、label1、textBox1 を配置したとします。
文字色を1つずつ設定すると、次のように書けます。
button1.ForeColor = Color.Navy;
label1.ForeColor = Color.Navy;
textBox1.ForeColor = Color.Navy;
3個なら問題ありませんが、コントロールが増えると同じ処理を何度も書くことになります。
③ Controlsをforeachで繰り返す
フォームが直接持っている子コントロールは、Controls コレクションに入っています。
foreach (Control control in Controls)
{
control.ForeColor = Color.Navy;
}
Controls の中には Button、Label、TextBox などが混ざっています。それでも、1個ずつ取り出す変数を Control 型にできます。
すべてが Control の一種だからです。

④ 共通の見た目をまとめて設定する
ForeColor と BackColor をまとめて設定してみましょう。
using System.Drawing;
using System.Windows.Forms;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ApplyCommonStyle();
}
private void ApplyCommonStyle()
{
foreach (Control control in Controls)
{
control.ForeColor = Color.Navy;
control.BackColor = Color.AliceBlue;
}
}
}
この処理では、各コントロール固有の機能は使っていません。Control に共通して用意されている ForeColor と BackColor だけを使っています。
「共通の型で受け取り、共通部分を操作する」と考えるのがポイントです。
⑤ Controlにはない固有機能を使いたい場合
Button だけの処理をしたい場合は、型を確認します。
foreach (Control control in Controls)
{
if (control is Button button)
{
button.Text = "ボタンです";
}
}
control is Button button は、次の2つを同時に行います。
controlの実体がButtonか確認するButtonとして使える変数buttonを用意する
Button ではない Label や TextBox は、if の中に入りません。
⑥ foreachで見えるのは直下の子だけ
ここは誤解しやすいポイントです。
foreach (Control control in Controls)
この Controls は、フォーム直下の子だけを表します。
たとえば、Panel の中に Button がある場合、フォームの Controls から直接見えるのは Panel です。中のボタンを見るには、panel1.Controls を調べます。
foreach (Control control in panel1.Controls)
{
control.ForeColor = Color.Navy;
}
「画面内のすべて」を再帰的に探す方法もありますが、まずはそれぞれの親が、自分の直下の子をControlsに持つと理解すれば十分です。
⑦ is-aとhas-aは別の関係
この例には、2種類の関係が登場します。
| 関係 | 例 | 意味 |
|---|---|---|
| is-a | Button は Control の一種 |
継承の関係 |
| has-a | フォームは子コントロールを持つ | Controls による所有・包含の関係 |
Button と Control は「種類」の関係です。一方、フォームとフォーム上のボタンは「持っている・含んでいる」という関係です。
似たように見えても、別の軸として整理しましょう。
⑧ MyButtonもControlとして扱える
前回作った MyButton も、同じ foreach に入ります。
MyButton → Button → Control
MyButton は Button を継承し、その Button が Control を継承しているからです。
このように、継承関係の途中に複数のクラスがあっても、共通の基底クラスとして扱えます。
⑨ 練習問題
① フォーム直下にあるすべてのコントロールの BackColor を Color.AliceBlue にしてみましょう。
② Label だけを見つけて、Text を「ラベルです」に変更してみましょう。
③ Panel の中にボタンを置き、フォームの Controls と panel1.Controls で見えるものが違うことを確認しましょう。
⑩ まとめ
Button、Label、TextBoxはすべてControlの一種foreach (Control control in Controls)で種類の違うコントロールをまとめて扱えるControl型のまま使えるのは、Controlに共通する機能- 固有機能を使うときは
isなどで実体の型を確認する - フォームの
Controlsで列挙できるのは直下の子 - is-a(継承)とhas-a(所有・包含)は別の関係
次回は、同じ MessageButton 型として扱っていても、実体によってクリック時のメッセージが変わる仕組みを学びます。
→ 次の記事:同じ型でも動きが変わる|ポリモーフィズムの入り口








ディスカッション
コメント一覧
まだ、コメントがありません