C#のShowDialogとは?使い方・戻り値・モーダル表示の基本を初心者向けに解説

はじめに

C#でWindows Formsアプリを作っていると、別画面を開く処理でShowDialogというメソッドをよく見かけます。

たとえば、設定画面を開いたり、入力画面を表示したり、OK・キャンセルの結果によって処理を分けたりするときに使われます。

ShowDialogは、単にフォームを表示するだけでなく、「表示したフォームを閉じるまで、元の画面を操作できない」という特徴があります。この仕組みを理解しておくと、フォーム間の値の受け渡しや、確認画面、設定画面などを作るときにとても便利です。

この記事では、C#のWindows FormsにおけるShowDialogについて、基本的な使い方、Showとの違い、戻り値であるDialogResult、フォーム間の値の受け渡し、よくある疑問まで初心者向けに解説します。

1. C#のShowDialogとは?

1-1. ShowDialogはフォームをモーダル表示するメソッド

ShowDialogは、C#のWindows Formsでフォームをモーダル表示するためのメソッドです。

フォームを表示するメソッドには主に次の2つがあります。

C#
form.Show();
form.ShowDialog();

Showは通常のフォーム表示、ShowDialogはダイアログとしてのフォーム表示です。

たとえば、親フォームから子フォームを開く場合、次のように書きます。

C#
using (Form2 form2 = new Form2())
{
form2.ShowDialog();
}

このコードを実行すると、Form2が表示されます。そして、Form2を閉じるまで、呼び出し元のフォームは操作できなくなります。

1-2. モーダル表示とは「閉じるまで親画面を操作できない表示」

ShowDialogの大きな特徴は、フォームをモーダル表示することです。

モーダル表示とは、表示された画面を閉じるまで、元の画面を操作できない表示方法のことです。

たとえば、アプリで設定画面を開いたときに、設定画面を閉じるまでメイン画面をクリックできないことがあります。このような表示がモーダル表示です。

一方で、メイン画面を操作しながら別画面も操作できる表示方法をモードレス表示と呼びます。C#のWindows Formsでは、モードレス表示にはShowを使います。

1-3. ShowDialogが使われる代表的な場面

ShowDialogは、ユーザーの入力や確認が必要な場面でよく使われます。

代表的な使用例は次のような場面です。

設定画面を開く場合、ユーザーがOKまたはキャンセルを選ぶまでメイン画面を操作させたくないことがあります。このような場合にShowDialogが向いています。

入力画面を開く場合も同じです。たとえば、ユーザー名や商品名などを入力してもらい、その結果を親フォームで受け取る場合に使えます。

また、確認画面として使うこともできます。「本当に削除しますか?」のような確認では、ユーザーの選択結果を待ってから次の処理を実行したいので、ShowDialogが便利です。

1-4. この記事で扱うShowDialogの前提:Windows Forms

この記事で解説するShowDialogは、C#のWindows Formsアプリケーションを前提にしています。

C#にはWindows Forms以外にも、WPF、MAUI、ASP.NETなどさまざまな開発環境があります。ShowDialogという名前のメソッドはWPFにもありますが、戻り値や使い方がWindows Formsとは少し異なります。

この記事では、次のようなWindows Formsのコードを中心に解説します。

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

namespace SampleApp
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
}
}

Windows Formsで別フォームを表示したい初心者の方は、まずこの記事の内容を理解しておくと、ShowDialogの基本をしっかり押さえられます。

2. ShowDialogの基本的な使い方

2-1. ShowDialogの基本構文

ShowDialogの基本構文は次のとおりです。

C#
フォームのインスタンス.ShowDialog();

実際のコードでは、表示したいフォームのインスタンスを作成してからShowDialogを呼び出します。

C#
Form2 form2 = new Form2();
form2.ShowDialog();

ただし、この書き方ではフォームを閉じたあとに明示的な破棄処理が必要になる場合があります。そのため、基本的にはusing文を使って書くことが多いです。

C#
using (Form2 form2 = new Form2())
{
form2.ShowDialog();
}

using文を使うと、ShowDialogで表示したフォームを閉じたあと、自動的にDisposeが呼ばれます。

2-2. 別フォームを作成して表示するサンプルコード

親フォームから別フォームを表示する基本的な例を見てみましょう。

たとえば、MainFormにボタンを配置し、そのボタンをクリックしたらSubFormを表示する場合は次のように書きます。

C#
private void buttonOpen_Click(object sender, EventArgs e)
{
using (SubForm subForm = new SubForm())
{
subForm.ShowDialog();
}
}

このコードでは、buttonOpenをクリックするとSubFormが表示されます。

SubFormが表示されている間、MainFormは操作できません。ユーザーがSubFormを閉じると、ShowDialogの次の処理に進みます。

2-3. 親フォームから子フォームを開く流れ

ShowDialogを使って親フォームから子フォームを開く流れは、基本的に次のようになります。

まず、親フォーム側で子フォームのインスタンスを作成します。

C#
SubForm subForm = new SubForm();

次に、作成した子フォームに対してShowDialogを呼び出します。

C#
subForm.ShowDialog();

最後に、子フォームを閉じたあと、必要であれば戻り値や入力された値を取得します。

C#
if (subForm.ShowDialog() == DialogResult.OK)
{
// OKが押されたときの処理
}

実際には、フォームの破棄も考えて、次のように書くのが基本です。

C#
using (SubForm subForm = new SubForm())
{
if (subForm.ShowDialog() == DialogResult.OK)
{
// OKが押されたときの処理
}
}

2-4. ShowDialog(this)で親フォームを指定する方法

ShowDialogには、親フォームを指定する書き方もあります。

C#
subForm.ShowDialog(this);

thisは、現在のフォームを表します。つまり、親フォームから子フォームを開く場合、次のように書けます。

C#
private void buttonOpen_Click(object sender, EventArgs e)
{
using (SubForm subForm = new SubForm())
{
subForm.ShowDialog(this);
}
}

ShowDialog(this)のように親フォームを指定すると、どのフォームの上にダイアログを表示するかが明確になります。

特に複数のフォームを扱うアプリでは、親フォームを指定しておくことで、ダイアログが意図しない位置や順序で表示される問題を避けやすくなります。

3. ShowDialogとShowの違い

3-1. ShowDialogはモーダル、Showはモードレス

ShowDialogShowの最大の違いは、表示方法です。

ShowDialogはモーダル表示です。表示されたフォームを閉じるまで、親フォームを操作できません。

C#
using (SubForm subForm = new SubForm())
{
subForm.ShowDialog();
}

一方、Showはモードレス表示です。表示されたフォームを開いたまま、親フォームも操作できます。

C#
SubForm subForm = new SubForm();
subForm.Show();

つまり、ユーザーの操作を一時的に子フォームへ集中させたい場合はShowDialogを使い、複数のフォームを同時に操作させたい場合はShowを使います。

3-2. ShowDialogは子フォームを閉じるまで次の処理に進まない

ShowDialogは、表示したフォームが閉じられるまで、呼び出し元の処理がそこで止まります。

たとえば、次のコードを見てください。

C#
private void buttonOpen_Click(object sender, EventArgs e)
{
using (SubForm subForm = new SubForm())
{
subForm.ShowDialog();
}

MessageBox.Show("子フォームが閉じられました");
}

この場合、SubFormが表示されている間は、次のMessageBox.Showは実行されません。

ユーザーがSubFormを閉じると、その後に「子フォームが閉じられました」というメッセージが表示されます。

この性質により、ShowDialogは「ユーザーの入力結果を待ってから処理したい」場合に向いています。

3-3. Showは表示後すぐに次の処理へ進む

Showは、フォームを表示したあと、すぐに次の処理へ進みます。

C#
private void buttonOpen_Click(object sender, EventArgs e)
{
SubForm subForm = new SubForm();
subForm.Show();

MessageBox.Show("子フォームを表示しました");
}

この場合、SubFormを閉じる前に「子フォームを表示しました」というメッセージが表示されます。

つまり、Showはフォームの終了を待ちません。

そのため、入力結果を待って処理を分岐したい場合にはShowではなくShowDialogを使うのが基本です。

3-4. ShowDialogとShowの使い分け

ShowDialogShowは、目的によって使い分けます。

ShowDialogが向いているのは、設定画面、入力画面、確認画面、選択画面などです。ユーザーがその画面で操作を完了するまで、親画面を操作してほしくない場合に使います。

一方、Showが向いているのは、ツールウィンドウ、ログ表示画面、サブ画面、プレビュー画面などです。親画面と子画面を同時に操作できても問題ない場合に使います。

たとえば、ユーザーに名前を入力してもらい、その名前を親フォームに反映したい場合はShowDialogが向いています。

反対に、ログ画面を開きながらメイン画面の処理を続けたい場合はShowが向いています。

4. ShowDialogの戻り値DialogResultとは?

4-1. ShowDialogの戻り値はDialogResult

ShowDialogは、フォームを表示するだけでなく、戻り値としてDialogResultを返します。

基本形は次のとおりです。

C#
DialogResult result = form.ShowDialog();

DialogResultは、ユーザーがダイアログをどのように閉じたかを表す値です。

よく使う値には、次のようなものがあります。

C#
DialogResult.OK
DialogResult.Cancel
DialogResult.Yes
DialogResult.No

たとえば、OKボタンが押されたときだけ処理を実行したい場合は、次のように書きます。

C#
using (SubForm subForm = new SubForm())
{
DialogResult result = subForm.ShowDialog();

if (result == DialogResult.OK)
{
MessageBox.Show("OKが押されました");
}
}

4-2. DialogResult.OKやCancelで処理を分岐する

ShowDialogの戻り値を使うと、OKが押された場合とキャンセルされた場合で処理を分けられます。

C#
using (SubForm subForm = new SubForm())
{
if (subForm.ShowDialog() == DialogResult.OK)
{
MessageBox.Show("OKが選択されました");
}
else
{
MessageBox.Show("キャンセルされました");
}
}

このように、ShowDialogは戻り値を使って処理を分岐できる点が重要です。

特に、入力画面や設定画面では、「OKが押されたときだけ内容を反映する」という処理がよく使われます。

4-3. ボタンのDialogResultプロパティを設定する方法

Windows Formsのボタンには、DialogResultプロパティがあります。

子フォームにOKボタンとキャンセルボタンを配置して、それぞれ次のように設定します。

OKボタンの場合は、DialogResultプロパティをOKにします。

C#
buttonOK.DialogResult = DialogResult.OK;

キャンセルボタンの場合は、DialogResultプロパティをCancelにします。

C#
buttonCancel.DialogResult = DialogResult.Cancel;

デザイナー画面から設定することもできます。ボタンを選択し、プロパティウィンドウでDialogResultOKCancelに変更します。

この設定をしておくと、ボタンをクリックしたときにフォームが閉じられ、ShowDialogの戻り値として設定した値が返ります。

4-4. OKボタン・キャンセルボタンの実装例

子フォームにOKボタンとキャンセルボタンがある場合の実装例を見てみましょう。

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

buttonOK.DialogResult = DialogResult.OK;
buttonCancel.DialogResult = DialogResult.Cancel;
}
}

親フォーム側では、次のようにShowDialogの戻り値を確認します。

C#
private void buttonOpen_Click(object sender, EventArgs e)
{
using (InputForm inputForm = new InputForm())
{
if (inputForm.ShowDialog() == DialogResult.OK)
{
MessageBox.Show("OKが押されました");
}
else
{
MessageBox.Show("キャンセルされました");
}
}
}

このように、子フォーム側でボタンのDialogResultを設定し、親フォーム側でShowDialogの戻り値を判定するのが基本的な使い方です。

4-5. 閉じるボタンで終了した場合の戻り値

フォーム右上の閉じるボタン、つまり「×」ボタンで閉じた場合、戻り値は多くの場合DialogResult.Cancelとして扱われます。

ただし、フォームの状態やDialogResultの設定によって結果が変わることもあります。

そのため、OKが押されたときだけ処理したい場合は、次のように明示的にDialogResult.OKを判定する書き方が安全です。

C#
using (InputForm inputForm = new InputForm())
{
if (inputForm.ShowDialog() == DialogResult.OK)
{
// OKが押されたときだけ実行する
}
}

この書き方にしておけば、キャンセルボタンや閉じるボタンで閉じた場合には処理を実行しないようにできます。

5. ShowDialogでフォーム間の値を受け渡しする方法

5-1. 子フォームで入力された値を親フォームで取得する

ShowDialogでは、子フォームで入力された値を親フォームで取得する使い方がよくあります。

たとえば、子フォームにテキストボックスを配置し、ユーザーが入力した名前を親フォームで取得するケースです。

流れは次のようになります。

まず、子フォームに入力用のTextBoxを配置します。

次に、子フォームに入力値を取得するためのpublicプロパティを用意します。

最後に、親フォームでShowDialogを呼び出し、OKが押された場合だけそのプロパティから値を取得します。

5-2. 子フォームにpublicプロパティを用意する

子フォーム側に、入力された値を外部から取得できるプロパティを用意します。

C#
public partial class InputForm : Form
{
public string InputText
{
get
{
return textBoxName.Text;
}
}

public InputForm()
{
InitializeComponent();

buttonOK.DialogResult = DialogResult.OK;
buttonCancel.DialogResult = DialogResult.Cancel;
}
}

この例では、InputTextというpublicプロパティを用意しています。

親フォーム側からは、inputForm.InputTextのようにして入力値を取得できます。

5-3. OKが押されたときだけ値を反映するサンプル

親フォーム側のコードは次のようになります。

C#
private void buttonOpen_Click(object sender, EventArgs e)
{
using (InputForm inputForm = new InputForm())
{
if (inputForm.ShowDialog(this) == DialogResult.OK)
{
labelName.Text = inputForm.InputText;
}
}
}

このコードでは、InputFormShowDialogで表示しています。

ユーザーがOKボタンを押した場合だけ、子フォームのInputTextを取得して、親フォームのlabelNameに反映します。

キャンセルボタンや閉じるボタンで閉じた場合は、値を反映しません。

このように、ShowDialogDialogResult.OKを組み合わせることで、「OKが押されたときだけ入力内容を反映する」という自然な動きを作れます。

5-4. 親フォームから子フォームへ初期値を渡す方法

親フォームから子フォームへ初期値を渡したい場合は、子フォームにプロパティやコンストラクターを用意します。

プロパティを使う例は次のとおりです。

C#
public partial class InputForm : Form
{
public string InputText
{
get
{
return textBoxName.Text;
}
set
{
textBoxName.Text = value;
}
}

public InputForm()
{
InitializeComponent();

buttonOK.DialogResult = DialogResult.OK;
buttonCancel.DialogResult = DialogResult.Cancel;
}
}

親フォーム側では、ShowDialogを呼び出す前に初期値を設定します。

C#
private void buttonOpen_Click(object sender, EventArgs e)
{
using (InputForm inputForm = new InputForm())
{
inputForm.InputText = labelName.Text;

if (inputForm.ShowDialog(this) == DialogResult.OK)
{
labelName.Text = inputForm.InputText;
}
}
}

このようにすると、子フォームを開いた時点で、親フォーム側の現在の値を初期値として表示できます。

設定画面や編集画面では、このように「現在の値を子フォームに渡し、OKが押されたら新しい値を反映する」という形がよく使われます。

6. ShowDialogの実践サンプル

6-1. 設定画面をShowDialogで開く例

アプリの設定画面は、ShowDialogの代表的な使い方です。

たとえば、ユーザー名を設定する画面を考えてみます。

子フォームであるSettingFormに次のようなプロパティを用意します。

C#
public partial class SettingForm : Form
{
public string UserName
{
get
{
return textBoxUserName.Text;
}
set
{
textBoxUserName.Text = value;
}
}

public SettingForm()
{
InitializeComponent();

buttonOK.DialogResult = DialogResult.OK;
buttonCancel.DialogResult = DialogResult.Cancel;
}
}

親フォーム側では、設定画面を次のように開きます。

C#
private void buttonSetting_Click(object sender, EventArgs e)
{
using (SettingForm settingForm = new SettingForm())
{
settingForm.UserName = labelUserName.Text;

if (settingForm.ShowDialog(this) == DialogResult.OK)
{
labelUserName.Text = settingForm.UserName;
}
}
}

このコードでは、設定画面でOKが押された場合だけ、ユーザー名を反映します。

キャンセルされた場合は、元の値を変更しません。

6-2. 入力ダイアログを作成する例

次に、簡単な入力ダイアログを作る例です。

子フォームInputFormにテキストボックスとOK・キャンセルボタンを配置します。

C#
public partial class InputForm : Form
{
public string Value
{
get
{
return textBoxValue.Text;
}
}

public InputForm()
{
InitializeComponent();

buttonOK.DialogResult = DialogResult.OK;
buttonCancel.DialogResult = DialogResult.Cancel;
}
}

親フォーム側では、次のように入力結果を取得します。

C#
private void buttonInput_Click(object sender, EventArgs e)
{
using (InputForm inputForm = new InputForm())
{
if (inputForm.ShowDialog(this) == DialogResult.OK)
{
MessageBox.Show("入力値: " + inputForm.Value);
}
}
}

このようにすると、ユーザーが入力した値を親フォームで利用できます。

6-3. 確認ダイアログとして使う例

ShowDialogは、独自の確認ダイアログを作るときにも使えます。

ただし、単純な確認だけならMessageBox.Showを使う方が簡単です。

C#
DialogResult result = MessageBox.Show(
"本当に削除しますか?",
"確認",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Question
);

if (result == DialogResult.OK)
{
// 削除処理
}

一方、独自のデザインや複雑な確認内容を表示したい場合は、専用フォームを作ってShowDialogで表示します。

C#
using (DeleteConfirmForm confirmForm = new DeleteConfirmForm())
{
if (confirmForm.ShowDialog(this) == DialogResult.OK)
{
// 削除処理
}
}

たとえば、削除対象の詳細情報を表示したり、チェックボックスで追加オプションを選ばせたりする場合には、独自フォームをShowDialogで開く方法が便利です。

6-4. MessageBox.Showとの違い

MessageBox.Showも、ShowDialogと似たようにユーザーの操作を待つダイアログを表示します。

たとえば、次のように使います。

C#
MessageBox.Show("保存しました");

確認結果を受け取ることもできます。

C#
DialogResult result = MessageBox.Show(
"終了しますか?",
"確認",
MessageBoxButtons.YesNo
);

if (result == DialogResult.Yes)
{
Application.Exit();
}

MessageBox.Showは、簡単なメッセージ表示や確認に向いています。

一方、ShowDialogは、自分で作成したフォームをダイアログとして表示したい場合に使います。

つまり、単純なメッセージならMessageBox.Show、入力欄や複雑なレイアウトが必要ならShowDialogと考えるとわかりやすいです。

7. ShowDialogを使うときの注意点

7-1. ShowDialogで開いたフォームはDisposeを忘れない

ShowDialogでフォームを表示した場合、フォームを閉じてもインスタンスがすぐに破棄されるとは限りません。

そのため、使い終わったフォームはDisposeで破棄することが重要です。

悪い例として、次のようなコードがあります。

C#
private void buttonOpen_Click(object sender, EventArgs e)
{
InputForm inputForm = new InputForm();
inputForm.ShowDialog();
}

この書き方でも動作はしますが、フォームの破棄が明示されていません。

小さなアプリでは問題が目立たないこともありますが、フォームを何度も開くようなアプリでは、リソース管理の面で望ましくありません。

7-2. using文でフォームを安全に破棄する

ShowDialogで表示するフォームは、基本的にusing文で囲むのがおすすめです。

C#
using (InputForm inputForm = new InputForm())
{
inputForm.ShowDialog(this);
}

このように書くと、usingブロックを抜けたタイミングで自動的にDisposeが呼ばれます。

戻り値を判定する場合も同じです。

C#
using (InputForm inputForm = new InputForm())
{
if (inputForm.ShowDialog(this) == DialogResult.OK)
{
// OK時の処理
}
}

初心者のうちは、ShowDialogを使うときはusing文とセットで覚えておくと安全です。

7-3. 同じフォームインスタンスを何度も使い回さない

ShowDialogで使うフォームは、必要なタイミングで新しく作成するのが基本です。

たとえば、次のようにクラスのフィールドとしてフォームを持ち、何度も使い回す書き方は注意が必要です。

C#
private InputForm inputForm = new InputForm();

private void buttonOpen_Click(object sender, EventArgs e)
{
inputForm.ShowDialog();
}

このような書き方をすると、前回の入力値や状態が残ったり、すでに破棄されたフォームを再利用してエラーになったりする可能性があります。

基本的には、次のように毎回新しいインスタンスを作成する方がわかりやすく安全です。

C#
private void buttonOpen_Click(object sender, EventArgs e)
{
using (InputForm inputForm = new InputForm())
{
inputForm.ShowDialog(this);
}
}

フォームの状態を引き継ぎたい場合は、フォーム自体を使い回すのではなく、必要な値をプロパティで渡す設計にすると扱いやすくなります。

7-4. 長時間処理をShowDialog内で実行すると画面が固まる

ShowDialogで表示したフォーム内で長時間処理を実行すると、画面が固まったように見えることがあります。

たとえば、ボタンクリック時に重い処理をそのまま実行すると、フォームが応答しなくなる場合があります。

C#
private void buttonExecute_Click(object sender, EventArgs e)
{
// 重い処理
System.Threading.Thread.Sleep(10000);

MessageBox.Show("完了しました");
}

このような処理は、UIスレッドを止めてしまうため、画面の再描画やボタン操作ができなくなります。

長時間かかる処理を行う場合は、asyncawaitを使って非同期処理にするなどの工夫が必要です。

C#
private async void buttonExecute_Click(object sender, EventArgs e)
{
buttonExecute.Enabled = false;

await Task.Run(() =>
{
// 時間のかかる処理
System.Threading.Thread.Sleep(10000);
});

buttonExecute.Enabled = true;
MessageBox.Show("完了しました");
}

ShowDialog自体が悪いわけではありませんが、ダイアログ内で重い処理を直接実行すると、操作性が悪くなる点に注意しましょう。

7-5. 戻り値が期待どおりにならないときの確認ポイント

ShowDialogの戻り値が期待どおりにならない場合は、まずボタンのDialogResultプロパティを確認しましょう。

OKボタンにDialogResult.OKが設定されていないと、親フォーム側で次の判定が期待どおりに動かないことがあります。

C#
if (inputForm.ShowDialog() == DialogResult.OK)
{
// 実行されない
}

子フォーム側で、次のように設定されているか確認します。

C#
buttonOK.DialogResult = DialogResult.OK;
buttonCancel.DialogResult = DialogResult.Cancel;

また、ボタンクリックイベント内でthis.DialogResultを設定する方法もあります。

C#
private void buttonOK_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
this.Close();
}

入力チェックを行いたい場合は、OKボタンが押されたときに入力内容を確認し、問題がある場合はフォームを閉じないようにすることもあります。

C#
private void buttonOK_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(textBoxName.Text))
{
MessageBox.Show("名前を入力してください");
this.DialogResult = DialogResult.None;
return;
}

this.DialogResult = DialogResult.OK;
this.Close();
}

このように、戻り値が期待どおりにならない場合は、ボタンのDialogResult、フォームの閉じ方、入力チェック処理を確認しましょう。

8. ShowDialogでよくあるエラー・疑問

8-1. ShowDialogを呼んでも親フォームが操作できないのはなぜ?

ShowDialogを呼ぶと親フォームが操作できなくなるのは、ShowDialogがモーダル表示だからです。

これはエラーではなく、ShowDialogの正常な動作です。

親フォームを操作できるようにしたい場合は、ShowDialogではなくShowを使います。

C#
SubForm subForm = new SubForm();
subForm.Show();

ただし、Showにすると、子フォームを閉じる前に親フォーム側の処理が進みます。

入力結果を待ちたい場合や、OK・キャンセルで処理を分けたい場合は、ShowDialogを使う方が適しています。

8-2. ShowDialogの戻り値がCancelになる原因

ShowDialogの戻り値がCancelになる主な原因は、キャンセルボタンや閉じるボタンでフォームが閉じられていることです。

また、OKボタンにDialogResult.OKが設定されていない場合も、期待した結果にならないことがあります。

次の設定を確認しましょう。

C#
buttonOK.DialogResult = DialogResult.OK;
buttonCancel.DialogResult = DialogResult.Cancel;

または、OKボタンのクリックイベントで明示的に設定します。

C#
private void buttonOK_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
this.Close();
}

親フォーム側では、OK以外はキャンセル扱いとして処理するのが一般的です。

C#
if (inputForm.ShowDialog(this) == DialogResult.OK)
{
// OKの場合だけ処理
}

8-3. フォームを閉じても値が取得できない原因

子フォームを閉じても値が取得できない場合は、値を取得するためのプロパティが正しく用意されているか確認しましょう。

たとえば、子フォーム側に次のようなプロパティが必要です。

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

親フォーム側では、usingブロックの中で値を取得します。

C#
using (InputForm inputForm = new InputForm())
{
if (inputForm.ShowDialog(this) == DialogResult.OK)
{
string text = inputForm.InputText;
MessageBox.Show(text);
}
}

注意点として、usingブロックを抜けたあとにフォームの値を取得しようとすると、すでにフォームが破棄されている場合があります。

そのため、値の取得はusingブロックの中で行うのが安全です。

8-4. ShowDialogとOpenFileDialog・SaveFileDialogの関係

OpenFileDialogSaveFileDialogも、ShowDialogを使って表示します。

たとえば、ファイルを開くダイアログは次のように書きます。

C#
using (OpenFileDialog dialog = new OpenFileDialog())
{
if (dialog.ShowDialog() == DialogResult.OK)
{
string fileName = dialog.FileName;
MessageBox.Show(fileName);
}
}

ファイルを保存するダイアログは次のように書きます。

C#
using (SaveFileDialog dialog = new SaveFileDialog())
{
if (dialog.ShowDialog() == DialogResult.OK)
{
string fileName = dialog.FileName;
MessageBox.Show(fileName);
}
}

このように、OpenFileDialogSaveFileDialogでも、ShowDialogの戻り値がDialogResult.OKかどうかを確認してから処理するのが基本です。

8-5. WPFのShowDialogとの違い

C#にはWindows Formsだけでなく、WPFにもShowDialogがあります。

ただし、Windows FormsとWPFでは戻り値の型が異なります。

Windows FormsのShowDialogは、基本的にDialogResultを返します。

C#
DialogResult result = form.ShowDialog();

一方、WPFのShowDialogは、bool?を返します。

C#
bool? result = window.ShowDialog();

WPFでは、OKの場合にtrue、キャンセルや閉じる場合にfalseまたはnullとして扱うことが多いです。

Windows FormsのコードをWPFにそのまま書き写すとエラーになる場合があるため、使用しているアプリの種類を確認することが大切です。

この記事で扱っているのは、Windows FormsのShowDialogです。

9. C#のShowDialogの理解を深めるポイント

9-1. ShowDialogは「入力・確認・選択」に向いている

ShowDialogは、ユーザーに何かを入力してもらう、確認してもらう、選択してもらう場面に向いています。

たとえば、次のような画面です。

設定画面では、ユーザーが設定を変更し、OKを押したときだけ反映できます。

入力画面では、ユーザーが入力した値を親フォームで取得できます。

確認画面では、ユーザーがOKやキャンセルを選ぶまで処理を止められます。

このように、ShowDialogは「ユーザーの操作結果を待つ必要がある画面」に使うと効果的です。

9-2. 戻り値DialogResultで処理を分岐するのが基本

ShowDialogを使うときは、戻り値であるDialogResultを使って処理を分岐するのが基本です。

特に重要なのは、OKが押されたときだけ処理を実行する書き方です。

C#
using (InputForm inputForm = new InputForm())
{
if (inputForm.ShowDialog(this) == DialogResult.OK)
{
// OKが押されたときだけ実行
}
}

この書き方を覚えておくと、設定画面、入力画面、確認画面など多くの場面で応用できます。

9-3. Showとの違いを理解して適切に使い分ける

ShowDialogShowの違いを理解しておくことも重要です。

ShowDialogは、子フォームを閉じるまで親フォームを操作できません。また、子フォームを閉じるまで次の処理へ進みません。

一方、Showは、子フォームを表示したあとすぐに次の処理へ進み、親フォームも操作できます。

入力結果を待ちたい場合はShowDialog、同時に複数画面を操作したい場合はShowと考えるとわかりやすいです。

9-4. 初心者がまず覚えるべきShowDialogの書き方

初心者がまず覚えるべきShowDialogの書き方は、次の形です。

C#
using (InputForm inputForm = new InputForm())
{
if (inputForm.ShowDialog(this) == DialogResult.OK)
{
// 子フォームの値を取得して処理する
}
}

子フォーム側では、OKボタンとキャンセルボタンにDialogResultを設定します。

C#
buttonOK.DialogResult = DialogResult.OK;
buttonCancel.DialogResult = DialogResult.Cancel;

値を渡したい場合は、子フォームにpublicプロパティを用意します。

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

この3つを覚えておくと、ShowDialogを使った基本的なダイアログ処理は十分に書けるようになります。

まとめ

C#のShowDialogは、Windows Formsでフォームをモーダル表示するためのメソッドです。

ShowDialogで表示したフォームは、閉じるまで親フォームを操作できません。そのため、設定画面、入力画面、確認画面など、ユーザーの操作結果を待ちたい場面に向いています。

ShowDialogの戻り値はDialogResultです。DialogResult.OKDialogResult.Cancelを使うことで、OKが押された場合、キャンセルされた場合、閉じるボタンで終了した場合などに応じて処理を分けられます。

基本的な書き方は次の形です。

C#
using (InputForm inputForm = new InputForm())
{
if (inputForm.ShowDialog(this) == DialogResult.OK)
{
// OKが押されたときの処理
}
}

また、子フォームで入力された値を親フォームで取得したい場合は、子フォームにpublicプロパティを用意します。

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

ShowDialogを使うときは、Showとの違い、DialogResultの使い方、フォームのDispose、フォーム間の値の受け渡しを押さえることが大切です。

初心者のうちは、ShowDialogは「閉じるまで親画面を操作できない表示」、DialogResultは「OKやキャンセルなどの結果を受け取る仕組み」と覚えておくと理解しやすいです。