【C#】FolderBrowserDialogでフォルダを選択させる実装手順:詳細解説
1. はじめに
ソフトウェア開発において、ユーザーに特定のフォルダを選択させる必要がある場面は頻繁に発生します。例えば、設定ファイルの保存場所を指定させたり、処理対象となる画像ファイル群が格納されているフォルダを指定させたりする場合です。このような「フォルダを選択させる」という機能を実現するために、Windowsアプリケーション開発では標準で提供されているダイアログボックスを使用するのが一般的です。C#/.NET Frameworkおよび.NET(旧称 .NET Core)のWindows Formsアプリケーションにおいては、System.Windows.Forms
名前空間に含まれるFolderBrowserDialog
クラスがその役割を担います。
FolderBrowserDialog
は、その名の通り、ユーザーがローカルコンピューター上のフォルダを階層的にブラウズし、最終的に一つのフォルダを選択するための標準的なダイアログボックスを提供します。このダイアログは、Windows OSの標準的な見た目に統合されており、ユーザーにとって馴染み深い操作感を提供します。
この記事では、C#を使用してFolderBrowserDialog
を効果的に利用するための詳細な手順、主要なプロパティ、実践的な使い方、そして注意点について、約5000語のボリュームで徹底的に解説します。さらに、より新しいAPIであるCommonOpenFileDialog
(Microsoft.WindowsAPICodePack.Dialogsライブラリ)を使った代替手段についても触れ、それぞれの利点と欠点を比較検討します。この記事を読むことで、あなたのアプリケーションにフォルダ選択機能を確実かつ柔軟に実装できるようになるでしょう。
2. FolderBrowserDialog の基本
まずはFolderBrowserDialog
を使用するための最も基本的なステップを見ていきましょう。
2.1. 名前空間
FolderBrowserDialog
クラスはSystem.Windows.Forms
名前空間に属しています。この名前空間は、Windows Formsアプリケーションを開発する際に、GUIコンポーネントやダイアログなどを扱うために必要です。したがって、コードファイルの先頭に以下のusing
ディレクティブを追加する必要があります。
csharp
using System.Windows.Forms;
通常、Windows Formsプロジェクトを作成すると、この名前空間は既に追加されていますが、念のため確認してください。
2.2. インスタンスの作成
FolderBrowserDialog
を使用するには、まずそのインスタンスを作成します。他のクラスと同様に、new
キーワードを使用してインスタンス化します。
csharp
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
2.3. ダイアログの表示 (ShowDialog()
メソッド)
インスタンスを作成したら、ShowDialog()
メソッドを呼び出すことで、フォルダ選択ダイアログを画面に表示します。このメソッドはモーダル(modal)でダイアログを表示します。モーダルダイアログとは、そのダイアログが表示されている間、親ウィンドウを含む他のアプリケーションウィンドウに対するユーザーの操作をブロックするダイアログのことです。ユーザーがダイアログを閉じない限り、アプリケーションの他の部分を操作することはできません。
ShowDialog()
メソッドは、ユーザーがダイアログをどのように閉じたかを示すDialogResult
列挙体の値を返します。
csharp
DialogResult result = folderBrowserDialog.ShowDialog();
2.4. 選択結果の取得 (DialogResult
)
ShowDialog()
メソッドが返すDialogResult
の値を確認することで、ユーザーが「OK」ボタンをクリックしてフォルダを選択したのか、それとも「キャンセル」ボタンや閉じるボタンをクリックして操作を取りやめたのかを判断できます。
DialogResult.OK
: ユーザーがフォルダを選択し、「OK」ボタンをクリックしてダイアログを閉じました。DialogResult.Cancel
: ユーザーが「キャンセル」ボタン、またはウィンドウの閉じるボタンをクリックしてダイアログを閉じました。
通常、ユーザーがフォルダを選択した(DialogResult.OK
の場合)にのみ、選択されたフォルダのパスを取得して処理を進めます。
csharp
if (result == DialogResult.OK)
{
// ユーザーがフォルダを選択した
// 次のステップで選択されたパスを取得する
}
else
{
// ユーザーがキャンセルした
// 何もしないか、適切なメッセージを表示するなどの処理
}
2.5. 選択されたフォルダのパスの取得 (SelectedPath
プロパティ)
ユーザーが「OK」ボタンをクリックしてダイアログを閉じた場合、選択されたフォルダの完全なパスはFolderBrowserDialog
インスタンスのSelectedPath
プロパティに格納されています。
csharp
string selectedFolderPath = folderBrowserDialog.SelectedPath;
このSelectedPath
プロパティの値は、ユーザーがDialogResult.OK
でダイアログを閉じた場合にのみ有効なパスを含んでいます。DialogResult.Cancel
でダイアログを閉じた場合、SelectedPath
プロパティは通常空の文字列(""
)となります。
2.6. 簡単なコード例
これらの基本的な要素を組み合わせた最も単純なFolderBrowserDialog
の使用例を以下に示します。これは、ボタンクリックなどのイベントハンドラ内に記述することを想定しています。
“`csharp
// using System.Windows.Forms; が必要
FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog();
// ダイアログを表示
DialogResult result = folderBrowserDialog1.ShowDialog();
// ユーザーがOKをクリックしたか確認
if (result == DialogResult.OK)
{
// 選択されたフォルダのパスを取得して表示(例えばMessageBoxで)
string selectedFolderPath = folderBrowserDialog1.SelectedPath;
MessageBox.Show(“選択されたフォルダ: ” + selectedFolderPath, “フォルダ選択完了”);
// ここで取得したselectedFolderPathを使って何らかの処理を行う
}
else
{
// ユーザーがキャンセルした場合
MessageBox.Show(“フォルダ選択はキャンセルされました。”, “キャンセル”);
}
// 注意:本来は using ステートメントを使うのが推奨されます(後述)
“`
このコードは、FolderBrowserDialog
を作成し、表示し、ユーザーの操作結果に応じて選択されたパスを取得・表示する基本的な流れを示しています。しかし、実際にはリソース管理の観点からusing
ステートメントを使用することが推奨されます。
3. FolderBrowserDialog の主要なプロパティ
FolderBrowserDialog
クラスは、ダイアログの見た目や振る舞いをカスタマイズするためのいくつかのプロパティを提供しています。ここでは、特によく使用される主要なプロパティについて詳しく見ていきましょう。
3.1. Description
プロパティ
Description
プロパティは、ダイアログウィンドウの上部に表示される説明テキストを設定します。ユーザーに、なぜフォルダの選択を求めているのか、どのようなフォルダを選択してほしいのかを伝えるために使用します。
csharp
folderBrowserDialog.Description = "処理対象のファイルが含まれるフォルダを選択してください。";
このテキストを設定することで、ユーザーはダイアログの目的をすぐに理解できます。設定しない場合、通常は何も表示されません(またはOSのデフォルトの短いテキスト)。
3.2. RootFolder
プロパティ
RootFolder
プロパティは、ダイアログの初期表示時にユーザーがブラウズを開始できる最上位のフォルダ(ルートフォルダ)を指定します。このプロパティを設定することで、ユーザーがシステム上のあらゆる場所を自由にブラウズできるのを制限し、特定の場所に誘導することができます。
このプロパティには、System.Environment.SpecialFolder
列挙体の値を指定します。SpecialFolder
列挙体は、Windows OSの標準的なシステムフォルダや特殊なフォルダ(例: デスクトップ、マイドキュメント、プログラムファイルなど)を表します。
Environment.SpecialFolder
列挙体には非常に多くの値がありますが、RootFolder
でよく使用される代表的な値をいくつか紹介します。
Desktop
: デスクトップフォルダ。MyDocuments
(またはMyDocuments
): ユーザーのドキュメントフォルダ(「ドキュメント」)。MyComputer
(またはComputer
): コンピューターのルート(「PC」や「コンピューター」)。これにより、ユーザーは全てのドライブやネットワークロケーションをブラウズできます。ProgramFiles
: プログラムファイルフォルダ(通常C:\Program Files
)。ProgramFilesX86
: 64ビットOS上の32ビットプログラムファイルフォルダ(通常C:\Program Files (x86)
)。CommonDocuments
: 全ユーザー共通のドキュメントフォルダ。UserProfile
: 現在ログインしているユーザーのプロファイルフォルダ。
例として、ドキュメントフォルダをルートとして開始させる場合:
csharp
folderBrowserDialog.RootFolder = Environment.SpecialFolder.MyDocuments;
例として、コンピューター全体をルートとして開始させる場合:
csharp
folderBrowserDialog.RootFolder = Environment.SpecialFolder.MyComputer;
RootFolder
プロパティの注意点:
RootFolder
を設定しても、ダイアログの 初期選択フォルダ がそのフォルダになるわけではありません。あくまで ブラウズ可能な最上位フォルダ が制限されるだけです。例えば、RootFolder = Environment.SpecialFolder.MyDocuments;
と設定しても、ダイアログが開いたときに最初に選択されているのは必ずしもマイドキュメントではなく、OSのデフォルト(通常は直前に開いたフォルダなど)になることがあります。初期選択フォルダを指定したい場合は、SelectedPath
プロパティを使用します(後述)。RootFolder
に設定したフォルダが存在しない場合や、アクセス権がない場合は、予期しない動作になることがあります。一般的には、ユーザーがアクセス可能な標準的なスペシャルフォルダを指定します。Environment.SpecialFolder
列挙体には多くの値がありますが、FolderBrowserDialog
がルートとして適切に扱えるのは一部の値のみです。上記の代表的な値は通常問題なく動作します。
Environment.SpecialFolder
列挙体の詳細な解説 (補足):
Environment.SpecialFolder
列挙体は非常に便利であり、RootFolder
以外でもアプリケーション内で特定のシステムフォルダのパスを取得する際にも使用されます。例えば、Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
のようにして、現在のユーザーのドキュメントフォルダのパスを文字列として取得できます。RootFolder
プロパティはこの列挙体と連携して動作します。
以下に、Environment.SpecialFolder
の主要な値をさらにリストアップし、その意味を簡単に説明します。これはRootFolder
として指定できるかどうかにかかわらず、パス取得などの場面で役立ちます。
ApplicationData
: 現在のユーザーのアプリケーション固有のデータ用フォルダ。ローミングプロファイル用。LocalApplicationData
: 現在のユーザーのアプリケーション固有のデータ用フォルダ。ローミングしない。CommonApplicationData
: 全ユーザー共通のアプリケーション固有のデータ用フォルダ。Cookies
: インターネット一時ファイルに関連するCookieフォルダ。History
: インターネット一時ファイルに関連する履歴フォルダ。InternetCache
: インターネット一時ファイルフォルダ。Programs
: [スタート] メニューのプログラムグループフォルダ。CommonPrograms
: 全ユーザー共通の [スタート] メニューのプログラムグループフォルダ。Startup
: 現在のユーザーのスタートアップフォルダ。CommonStartup
: 全ユーザー共通のスタートアップフォルダ。Recent
: 最近使ったドキュメントフォルダ。SendTo
: [送る] メニューのフォルダ。StartMenu
: [スタート] メニューのフォルダ。CommonStartMenu
: 全ユーザー共通の [スタート] メニューのフォルダ。Templates
: ドキュメントテンプレートフォルダ。CommonTemplates
: 全ユーザー共通のドキュメントテンプレートフォルダ。DesktopDirectory
: デスクトップの物理パス。Personal
:MyDocuments
と同じ。Favorites
: お気に入りフォルダ。NetworkShortcuts
: ネットワークショートカットフォルダ。Fonts
: フォントフォルダ。System
: Windows システムフォルダ。ProgramFiles
: プログラムファイルフォルダ (x86ではない方)。CommonProgramFiles
: 全ユーザー共通のプログラムファイルフォルダ。SystemX86
: 64ビットOS上の32ビットWindowsシステムフォルダ。ProgramFilesX86
: 64ビットOS上の32ビットプログラムファイルフォルダ。CommonProgramFilesX86
: 64ビットOS上の全ユーザー共通の32ビットプログラムファイルフォルダ。Connections
: ネットワーク接続フォルダ。Printers
: プリンターフォルダ。MyMusic
(またはMusic
): ユーザーの音楽フォルダ。MyPictures
(またはPictures
): ユーザーの画像フォルダ。MyVideos
(またはVideos
): ユーザーのビデオフォルダ。Desktop
: デスクトップ仮想フォルダ。Computer
: コンピューター仮想フォルダ。PrintersFolder
: プリンター仮想フォルダ。InternetExplorerFavorites
: IEのお気に入りフォルダ。AdminTools
: 管理ツールフォルダ。CommonAdminTools
: 全ユーザー共通の管理ツールフォルダ。CDBurning
: CD書き込み用ステージングフォルダ。Contacts
: ユーザーの連絡先フォルダ(Windows Vista以降)。Links
: ユーザーのリンクフォルダ(Windows Vista以降)。OneDrive
: OneDriveフォルダ(Windows 8.1以降、OSとの統合による)。SavedSearches
: 保存された検索フォルダ(Windows Vista以降)。
これらのうち、RootFolder
として特に有用なのは Desktop
, MyComputer
(または Computer
), MyDocuments
(または Personal
), ProgramFiles
, ProgramFilesX86
など、ファイルシステムの階層構造のルートとなりうるようなフォルダです。
3.3. SelectedPath
プロパティ
SelectedPath
プロパティは、ShowDialog()
メソッドからDialogResult.OK
が返された後に、ユーザーが選択したフォルダの完全なパス(文字列)を取得するために使用されます。
csharp
string selectedPath = folderBrowserDialog.SelectedPath;
// selectedPath には例えば "C:\\Users\\YourName\\Documents\\MyAppFolder" のような文字列が入る
また、ShowDialog()
メソッドを呼び出す 前に このプロパティに既存のフォルダパスを設定することで、ダイアログを開いたときに特定のフォルダが初期選択されている状態にすることができます。これは、前回のユーザーの選択を記憶しておき、次回ダイアログを開くときにそのフォルダをデフォルトとして表示したい場合などに便利です。
“`csharp
// アプリケーションの設定から前回のパスを読み込むなどの想定
string lastUsedPath = “C:\Users\YourName\Desktop”; // 例として固定パスを指定
if (System.IO.Directory.Exists(lastUsedPath)) // フォルダが存在するか確認するのが安全
{
folderBrowserDialog.SelectedPath = lastUsedPath;
}
else
{
// 存在しない場合はデフォルトのRootFolderから開始するなど
folderBrowserDialog.RootFolder = Environment.SpecialFolder.Desktop;
}
DialogResult result = folderBrowserDialog.ShowDialog();
if (result == DialogResult.OK)
{
string newSelectedPath = folderBrowserDialog.SelectedPath;
// newSelectedPath を設定に保存するなどの処理
}
“`
SelectedPath
に存在しないパスを設定した場合の挙動は、OSのバージョンやAutoUpgradeEnabled
の設定によって異なることがありますが、一般的にはエラーにはならず、デフォルトの開始フォルダからダイアログが開かれるか、指定されたパスに近い有効なフォルダが選択されるかのどちらかになります。確実に指定したフォルダから開始させたい場合は、パスの存在を確認してから設定するのが良いでしょう。
3.4. ShowNewFolderButton
プロパティ
ShowNewFolderButton
プロパティは、フォルダ選択ダイアログに「新しいフォルダーの作成」ボタンを表示するかどうかを制御します。デフォルトはtrue
で、ボタンが表示されます。ユーザーが選択したいフォルダがまだ存在しない場合に、ダイアログ内で新しくフォルダを作成することを許可するかどうかを指定します。
true
(デフォルト): 「新しいフォルダーの作成」ボタンが表示され、ユーザーはダイアログ内で新しいフォルダを作成できます。false
: 「新しいフォルダーの作成」ボタンは表示されません。
csharp
// 新しいフォルダ作成を許可しない場合
folderBrowserDialog.ShowNewFolderButton = false;
3.5. UseDescriptionForTitle
プロパティ (非推奨)
UseDescriptionForTitle
プロパティは、Description
プロパティで設定したテキストをダイアログのタイトルバーに表示するかどうかを制御します。デフォルトはfalse
です。このプロパティは古いスタイルのダイアログ(Windows XP以前の見た目)に対応するために存在しており、Windows Vista以降の新しいスタイルのダイアログでは通常効果がありません(AutoUpgradeEnabled
がtrue
の場合)。新しいアプリケーションでは通常このプロパティを使用する必要はありませんが、互換性のために知っておくと良いでしょう。
3.6. AutoUpgradeEnabled
プロパティ
AutoUpgradeEnabled
プロパティは、FolderBrowserDialog
が新しいスタイルのUI(Windows Vista以降で導入された、よりモダンで機能豊富なダイアログ)を使用するかどうかを制御します。デフォルトはtrue
です。
true
(デフォルト): 可能であれば、Windows Vista以降の新しいスタイルのダイアログが使用されます。このダイアログは、Windows Explorerと統合されており、ピン留めされたフォルダ、ジャンプリスト、ナビゲーションペインなどをサポートします。見た目も現在のWindows OSに合っています。false
: 常に古いスタイルのダイアログ(Windows XP以前の見た目)が使用されます。
csharp
// 古いスタイルのダイアログを強制する場合(特別な理由がない限り推奨されない)
folderBrowserDialog.AutoUpgradeEnabled = false;
通常はデフォルトのtrue
のままにしておくことが推奨されます。新しいスタイルのダイアログはユーザーエクスペリエンスの観点から優れています。ただし、古いスタイルでしか利用できない機能がある場合や、特定の互換性要件がある場合にのみfalse
に設定を検討します。しかし、古いスタイルのダイアログはWindowsのモダンなフォルダ構造(ライブラリなど)をうまく扱えない場合があるため注意が必要です。
3.7. その他のプロパティ
HelpRequest
: ダイアログでヘルプボタンがクリックされたり、F1キーが押されたりしたときに発生するイベント。独自のヘルプシステムを統合したい場合に使用しますが、あまり一般的ではありません。
これらのプロパティを適切に設定することで、アプリケーションの要件に合わせたフォルダ選択ダイアログを提供できます。
4. ShowDialog() メソッドの詳細
ShowDialog()
メソッドは、単にダイアログを表示するだけでなく、いくつかの重要な側面があります。
4.1. 戻り値 DialogResult
前述の通り、ShowDialog()
メソッドはDialogResult
を返します。この戻り値をチェックすることは、ユーザーの意図を正しく判断し、その後の処理を分岐させるために不可欠です。
“`csharp
DialogResult result = folderBrowserDialog.ShowDialog();
if (result == DialogResult.OK)
{
// ユーザーがフォルダを選択し、確定した
string selectedFolderPath = folderBrowserDialog.SelectedPath;
// selectedFolderPath を使用した処理…
}
else if (result == DialogResult.Cancel)
{
// ユーザーがキャンセルした
// 例: 処理を中断する、ユーザーにキャンセルされたことを通知するなど
MessageBox.Show(“フォルダ選択がキャンセルされました。”, “通知”);
}
// DialogResult には他にも Abort, Retry, Ignore, Yes, No がありますが、
// FolderBrowserDialog の ShowDialog() が返すのは通常 OK または Cancel のみです。
“`
4.2. ShowDialog(IWin32Window owner)
オーバーロード
ShowDialog()
メソッドには、親ウィンドウを指定できるオーバーロードが存在します。
csharp
DialogResult ShowDialog(IWin32Window owner);
IWin32Window
インターフェースは、ウィンドウハンドルを持つオブジェクトを表します。通常、Windows Formsアプリケーションでは、フォームクラス自身(this
キーワード)や他のコントロールがこのインターフェースを実装しています。親ウィンドウを指定してダイアログを表示すると、以下の利点があります。
- モーダル表示の関連付け: ダイアログは指定された親ウィンドウの「上」に表示され、親ウィンドウが最小化されると一緒に最小化されるなど、親子関係が明確になります。
- タスクバー: 親ウィンドウを指定しない場合、ダイアログがタスクバーに独自の項目として表示されることがあります。親ウィンドウを指定すると、ダイアログは親ウィンドウのタスクバー項目に関連付けられ、より一貫したユーザーエクスペリエンスを提供します。
- zオーダー: 親ウィンドウの前面に常に表示されるようになります。
したがって、特に複数のウィンドウを持つアプリケーションでは、どのウィンドウからダイアログを呼び出したのかを明確にするために、親ウィンドウを指定することが強く推奨されます。
“`csharp
// これはFormクラスのメソッド内(例: ボタンのクリックイベントハンドラ)での記述を想定
// this は現在のFormインスタンスを指す
DialogResult result = folderBrowserDialog.ShowDialog(this);
if (result == DialogResult.OK)
{
string selectedFolderPath = folderBrowserDialog.SelectedPath;
// 処理…
}
“`
4.3. using
ステートメントを使ったリソース解放
FolderBrowserDialog
クラスは、基となるWindows APIのリソースを使用します。これらのリソースは、ダイアログが不要になったときに適切に解放される必要があります。FolderBrowserDialog
はIDisposable
インターフェースを実装しているため、using
ステートメントを使用してインスタンスを作成・表示するのが最も安全で推奨される方法です。using
ブロックを抜けるときに、インスタンスのDispose()
メソッドが自動的に呼び出され、リソースが解放されます。
“`csharp
// using System.Windows.Forms; が必要
// FolderBrowserDialog インスタンスを using ブロック内で作成
using (FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog())
{
// プロパティの設定
folderBrowserDialog.Description = “設定ファイルを保存するフォルダを選択してください。”;
folderBrowserDialog.RootFolder = Environment.SpecialFolder.Desktop;
folderBrowserDialog.SelectedPath = “C:\DefaultPath”; // 例: 存在しない可能性のあるパス
folderBrowserDialog.ShowNewFolderButton = true;
// folderBrowserDialog.AutoUpgradeEnabled = true; // デフォルトなので通常不要
// ダイアログを表示 (親ウィンドウを指定するのが推奨)
DialogResult result = folderBrowserDialog.ShowDialog(this); // this は Form インスタンスを指す
// 結果の処理
if (result == DialogResult.OK)
{
string selectedFolderPath = folderBrowserDialog.SelectedPath;
// 選択されたフォルダパスを使った処理...
MessageBox.Show("選択されたフォルダ: " + selectedFolderPath, "完了");
}
else
{
// キャンセル時の処理
MessageBox.Show("フォルダ選択がキャンセルされました。", "通知");
}
// using ブロックを抜けると、folderBrowserDialog.Dispose() が自動的に呼び出される
} // ここで Dispose() が呼ばれる
“`
このusing
パターンは、リソースリークを防ぐために非常に重要です。FolderBrowserDialog
を使用する際は、常にこのパターンを採用するようにしましょう。
5. 実践的な使用例 (Windows Forms アプリケーション)
ここでは、実際のWindows Formsアプリケーションのシナリオを想定して、FolderBrowserDialog
を使用する具体的な手順をステップバイステップで説明します。
シナリオ:
ユーザーに特定の作業フォルダを選択させ、そのパスをアプリケーションのウィンドウに表示する。
アプリケーションの構成:
* シンプルなフォーム (Form1
)
* フォルダ選択ボタン (Button
): btnSelectFolder
* 選択されたフォルダパスを表示するテキストボックス (TextBox
): txtFolderPath
* 説明ラベル (Label
)
実装手順:
- Windows Formsプロジェクトの作成: Visual Studioで新しいC#のWindows Formsアプリケーションプロジェクトを作成します。プロジェクト名は任意です(例:
FolderSelectorApp
)。 -
フォームデザイン:
Form1
のデザインビューを開き、以下のコントロールをツールボックスから配置します。Label
: テキストを「選択されたフォルダパス:」などに設定。TextBox
: 名前をtxtFolderPath
に設定。幅を広めに調整し、ReadOnly
プロパティをtrue
に設定すると、ユーザーが直接編集できない表示専用フィールドとして使えます。Button
: 名前をbtnSelectFolder
、テキストを「フォルダを選択…」などに設定。
コントロールをフォーム上に適切に配置・整列させます。
![フォームデザインイメージ(ここではテキストで表現)]
“`
Form1 [ラベル] 選択されたフォルダパス: [テキストボックス txtFolderPath ] [ボタン btnSelectFolder ]
“`
-
イベントハンドラの作成:
btnSelectFolder
ボタンをダブルクリックし、Click
イベントハンドラを自動生成します。コードエディタに以下のメソッドスタブが表示されます。csharp
private void btnSelectFolder_Click(object sender, EventArgs e)
{
// ここにフォルダ選択ダイアログのコードを記述
} -
FolderBrowserDialog
の実装: 生成されたbtnSelectFolder_Click
メソッド内に、FolderBrowserDialog
を使用するコードを記述します。using
ステートメントを使用し、親ウィンドウとして現在のフォーム (this
) を指定します。“`csharp
private void btnSelectFolder_Click(object sender, EventArgs e)
{
// FolderBrowserDialog のインスタンスを using ブロックで作成
using (FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog())
{
// ダイアログ上部に表示する説明を設定
folderBrowserDialog.Description = “処理対象のフォルダを選択してください。”;// ダイアログを開いたときの初期フォルダを指定(オプション) // 例: デスクトップをルートとして開始 folderBrowserDialog.RootFolder = Environment.SpecialFolder.Desktop; // 例: テキストボックスに前回のパスがあればそれを初期選択にする if (System.IO.Directory.Exists(txtFolderPath.Text)) { folderBrowserDialog.SelectedPath = txtFolderPath.Text; } else { // 前回のパスが無効な場合、デフォルトのパスやルートフォルダから開始 // この例では RootFolder (デスクトップ) から開始される } // 新しいフォルダを作成するボタンを表示するかどうか (デフォルトは true) folderBrowserDialog.ShowNewFolderButton = true; // ダイアログを表示し、結果を取得 // 親ウィンドウとして現在のフォーム (this) を指定 DialogResult result = folderBrowserDialog.ShowDialog(this); // ユーザーがOKボタンをクリックしたか判定 if (result == DialogResult.OK) { // 選択されたフォルダのパスを取得 string selectedFolderPath = folderBrowserDialog.SelectedPath; // 取得したパスをテキストボックスに表示 txtFolderPath.Text = selectedFolderPath; // 選択されたフォルダパスを使って、ここから他の処理を続ける // 例: MessageBox.Show($"フォルダ '{selectedFolderPath}' が選択されました。"); } else { // ユーザーがキャンセルした場合 // 例: テキストボックスの内容をクリアするなど // txtFolderPath.Text = ""; // キャンセル時にクリアしたい場合 MessageBox.Show("フォルダ選択がキャンセルされました。", "通知"); } } // using ブロックを抜けると、folderBrowserDialog.Dispose() が呼ばれる
}
“` -
実行: アプリケーションを実行します。
- フォームが表示されます。「フォルダを選択…」ボタンをクリックします。
FolderBrowserDialog
が表示されます。Description
で指定したテキストが上部に表示され、RootFolder
で指定したデスクトップからブラウズが開始されます(ただし初期選択は異なる可能性あり)。ShowNewFolderButton
がtrue
であれば、「新しいフォルダーの作成」ボタンが表示されます。- 任意のフォルダを選択し、「OK」をクリックします。
- ダイアログが閉じられ、選択したフォルダのパスがフォーム上のテキストボックス
txtFolderPath
に表示されます。 - 「キャンセル」をクリックした場合、テキストボックスは変更されず、キャンセルされた旨のメッセージが表示されます。
この例は、FolderBrowserDialog
の基本的なプロパティとメソッドを使用して、ユーザーからフォルダパスを取得する一連の流れを示しています。SelectedPath
に前回の値を設定する部分は、アプリケーションの状態(設定ファイルなど)から最後に使用したフォルダパスを読み込んで利用する実際のシナリオを想定しています。パスが存在しない場合のエラー処理も、System.IO.Directory.Exists()
メソッドを使って適切に行うことが重要です。
6. エラーハンドリングと注意点
FolderBrowserDialog
を使用する際に考慮すべきいくつかの点があります。
6.1. ユーザーがキャンセルした場合の処理
最も基本的なエラーハンドリングは、ユーザーがダイアログをキャンセルした場合の処理です。ShowDialog()
メソッドの戻り値がDialogResult.Cancel
の場合、SelectedPath
プロパティは信頼できるパスを含んでいません(通常は空文字列)。したがって、常にDialogResult.OK
の場合のみSelectedPath
を使用するようにコードを記述する必要があります。上記のコード例はこの点に注意して記述されています。
6.2. セキュリティに関する注意点
ユーザーが選択したフォルダパスは、アプリケーション内でファイル操作(読み込み、書き込み、削除など)に使用されることが想定されます。アプリケーションが選択されたパスに対して適切なアクセス権を持っているか確認する必要があります。ただし、FolderBrowserDialog
自体はアクセス権のチェックは行いません。ファイル操作時には、System.IO
名前空間のメソッドが適切な例外(例: UnauthorizedAccessException
)をスローするため、これらの例外を適切にキャッチして処理する必要があります。
また、アプリケーションが部分信頼の環境(例: ClickOnceでインターネットゾーンから配布されたアプリケーション)で実行される場合、ファイルシステムへのアクセスにはセキュリティ制限がかかる可能性があります。その場合、特定のフォルダへのアクセスが許可されない場合があります。
6.3. SelectedPath
が空になるケース
前述の通り、DialogResult.Cancel
の場合、SelectedPath
は空文字列になります。また、ダイアログを開く前にSelectedPath
に存在しないパスを設定した場合、ダイアログが開いてもそのパスは選択されません。ユーザーが何もフォルダを選択せずに「OK」ボタンをクリックした場合(これは新しいスタイルのダイアログでは通常不可能な操作ですが、古いスタイルではありえました)、SelectedPath
が空文字列になる可能性もあります。コードでSelectedPath
を使用する前に、それが空文字列でないか、または有効なパスであるかを確認する(例: System.IO.Directory.Exists()
を使用するなど)のが安全です。
csharp
if (result == DialogResult.OK)
{
string selectedFolderPath = folderBrowserDialog.SelectedPath;
if (!string.IsNullOrEmpty(selectedFolderPath) && System.IO.Directory.Exists(selectedFolderPath))
{
// パスが有効であることを確認してから使用
txtFolderPath.Text = selectedFolderPath;
// ... 処理 ...
}
else
{
// 何らかの理由で有効なパスが取得できなかった場合
MessageBox.Show("選択されたフォルダが有効ではありません。", "エラー");
// txtFolderPath.Text = "";
}
}
6.4. 古いスタイルと新しいスタイルの違い (AutoUpgradeEnabled
)
AutoUpgradeEnabled
プロパティで説明したように、Windows XP以前のスタイルとWindows Vista以降の新しいスタイルでは、FolderBrowserDialog
の見た目と一部の挙動が異なります。新しいスタイルはOSのシェルに統合されており、ユーザーはライブラリ、ピン留めされたフォルダ、ネットワークロケーションなどをより自然にブラウズできます。古いスタイルはより単純で、物理的なファイルシステム構造をツリービューで表示する形式です。
ほとんどの場合、AutoUpgradeEnabled = true
(デフォルト) のまま新しいスタイルを使用するのが最善です。古いスタイルが必要になるのは、特定の環境での互換性維持や、新しいスタイルで発生する特定のバグや問題へのワークアラウンドなど、まれなケースに限られます。古いスタイルのダイアログは、Vista以降で導入された「ライブラリ」のような概念を理解できないため、正確なパスを取得できないことがあります。
6.5. UIスレッド以外からの呼び出し
Windows Formsコントロール(FolderBrowserDialog
を含む)は、そのインスタンスが作成されたUIスレッドからのみアクセスされる必要があります。UIスレッド以外のスレッド(例: バックグラウンドワーカースレッド)からShowDialog()
を呼び出そうとすると、InvalidOperationException
が発生します。
もしバックグラウンド処理中にダイアログを表示する必要が生じた場合は、Form
やコントロールのInvoke
またはBeginInvoke
メソッドを使用して、UIスレッド上でダイアログを表示するコードを実行する必要があります。
“`csharp
// バックグラウンドスレッド内からのUI操作例 (これはButtonのClickイベントハンドラとは別の場所を想定)
private void BackgroundProcess()
{
// バックグラウンド処理…
// UIスレッドでダイアログを表示する必要がある場合
if (this.InvokeRequired) // 現在のメソッドがUIスレッドで実行されているか確認
{
// UIスレッドに処理を委譲
this.Invoke((MethodInvoker)delegate {
ShowFolderBrowserDialog(); // UI操作を含むメソッドを呼び出す
});
}
else
{
// UIスレッドで実行されている場合
ShowFolderBrowserDialog();
}
// バックグラウンド処理の続き...
}
// UIスレッドで実行される、ダイアログ表示と結果処理のメソッド
private void ShowFolderBrowserDialog()
{
using (FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog())
{
folderBrowserDialog.Description = “ログファイルの保存先を選択してください。”;
DialogResult result = folderBrowserDialog.ShowDialog(this); // 親ウィンドウを指定
if (result == DialogResult.OK)
{
string selectedFolderPath = folderBrowserDialog.SelectedPath;
// UIコントロールにパスを表示するなど (Invokeは不要、UIスレッドで実行されているため)
txtFolderPath.Text = selectedFolderPath;
// ... 選択パスを使った処理 (必要に応じてUIスレッド以外で実行)
}
}
}
“`
7. 代替手段と進化:CommonOpenFileDialog
FolderBrowserDialog
は標準的で使いやすいダイアログですが、Windows Vista以降で導入された新しいファイル/フォルダ選択ダイアログ(いわゆるVistaスタイルのダイアログ)の全ての機能を利用できるわけではありません。特に、エクスプローラーのナビゲーションペインに表示される「ライブラリ」や「ホームグループ」(旧)、モダンな検索機能などは、FolderBrowserDialog
の新しいスタイル(AutoUpgradeEnabled = true
)でも一部制限があります。
よりモダンで機能豊富なダイアログを使用したい場合は、Microsoft.WindowsAPICodePack.Dialogs
ライブラリに含まれるCommonOpenFileDialog
クラスを検討する価値があります。このライブラリは、Windows Vista以降の共通ダイアログAPI(Common Item Dialog API)を.NETから簡単に利用できるようにするものです。
7.1. CommonOpenFileDialog
とは
CommonOpenFileDialog
は、ファイルを開く(Open)ダイアログまたはフォルダを選択するダイアログとして機能させることができます。FolderBrowserDialog
よりも多くのプロパティとイベントを提供し、より高度なカスタマイズや、Windows Explorerの機能(ライブラリ、ピン留め、プレビューペインなど)との連携が可能です。
7.2. FolderBrowserDialog
より優れている点
- モダンなUI: Windows Explorerと完全に統合された最新のUIを提供します。
- ライブラリと特殊フォルダ: 「ドキュメント」「ピクチャ」などのライブラリや、OneDrive、ネットワークロケーションなどをネイティブに扱えます。
- ピン留めとジャンプリスト: エクスプローラーでピン留めされたフォルダや、最近使用したフォルダ(ジャンプリスト)が表示されます。
- プレビューペイン: ファイル選択モードの場合、選択したファイルのプレビューを表示できます(フォルダ選択モードでは関係ありません)。
- より柔軟な設定: 初期ディレクトリ、フィルター、複数のファイル/フォルダ選択の可否など、
FolderBrowserDialog
よりも多くのオプションを設定できます。 - パフォーマンス: 大量のファイルやフォルダを含むディレクトリでも、古いダイアログよりも高速に表示されることがあります。
7.3. CommonOpenFileDialog
を使用する場合のセットアップ
CommonOpenFileDialog
は.NET Frameworkや.NETの標準ライブラリには含まれていません。NuGetパッケージとして別途追加する必要があります。
- Visual Studioの「NuGetパッケージの管理」を開きます。(ソリューションエクスプローラーでプロジェクトを右クリック -> 「NuGetパッケージの管理」)
- 「参照」タブを選択し、「Microsoft.WindowsAPICodePack.Shell」を検索します。
- 検索結果から「Microsoft.WindowsAPICodePack.Shell」を選択し、インストールします。
- 同様に、「Microsoft.WindowsAPICodePack.Core」も検索・インストールします。(DialogsはShellパッケージに含まれていることが多いですが、Coreも必要です)
インストールが完了したら、コードファイルの先頭に以下のusing
ディレクティブを追加します。
csharp
using Microsoft.WindowsAPICodePack.Dialogs;
7.4. CommonOpenFileDialog
を使ったフォルダ選択のコード例
CommonOpenFileDialog
をフォルダ選択ダイアログとして使用するには、インスタンスを作成し、IsFolderPicker
プロパティをtrue
に設定します。
“`csharp
using Microsoft.WindowsAPICodePack.Dialogs;
// using System.Windows.Forms; も必要
private void btnSelectFolder_Common_Click(object sender, EventArgs e)
{
// CommonOpenFileDialog のインスタンスを using ブロックで作成
using (CommonOpenFileDialog commonOpenFileDialog = new CommonOpenFileDialog())
{
// これを true にすることで、フォルダ選択ダイアログとして機能させる
commonOpenFileDialog.IsFolderPicker = true;
// ダイアログのタイトルを設定 (FolderBrowserDialog の Description に相当)
commonOpenFileDialog.Title = "処理対象のフォルダを選択";
// ダイアログを開いたときの初期フォルダを指定 (オプション)
// InitialDirectory プロパティを使用
// Environment.GetFolderPath を使うと SpecialFolder のパスを取得できる
commonOpenFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
// テキストボックスに前回のパスがあればそれを初期選択にする (オプション)
if (System.IO.Directory.Exists(txtFolderPath.Text))
{
commonOpenFileDialog.InitialDirectory = txtFolderPath.Text; // これが優先される傾向
commonOpenFileDialog.DefaultDirectory = txtFolderPath.Text; // こちらも設定しておくとより確実
}
else
{
commonOpenFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
}
// 新しいフォルダを作成するボタンを表示するかどうか
// CommonOpenFileDialog では Options プロパティの EnableCreateFolder を使う
commonOpenFileDialog.EnsureValidNames = false; // 不要なエラー回避のために false にすることが多い
commonOpenFileDialog.AllowNonFileSystemItems = false; // ファイルシステム項目のみを選択可能にする
// commonOpenFileDialog.Options = CommonFileDialogOptions.ForceFileSystem; // これも使える
// ダイアログを表示し、結果を取得
// ShowDialog() は WinForms の DialogResult ではなく CommonFileDialogResult を返す
CommonFileDialogResult result = commonOpenFileDialog.ShowDialog(); // 親ウィンドウ指定のオーバーロードもある
// ユーザーがOKボタンをクリックしたか判定
if (result == CommonFileDialogResult.Ok)
{
// 選択されたフォルダのパスを取得
// FileName プロパティにフォルダパスが入る (CommonOpenFileDialog はファイル/フォルダ両用のため)
string selectedFolderPath = commonOpenFileDialog.FileName;
// 取得したパスをテキストボックスに表示
txtFolderPath.Text = selectedFolderPath;
// 選択されたフォルダパスを使った処理を続ける
MessageBox.Show($"共通ダイアログで選択されたフォルダ: {selectedFolderPath}", "完了 (Common)");
}
else
{
// ユーザーがキャンセルした場合
MessageBox.Show("共通ダイアログでのフォルダ選択がキャンセルされました。", "通知 (Common)");
}
} // using ブロックを抜けると Dispose() が呼ばれる
}
“`
CommonOpenFileDialog
はFolderBrowserDialog
よりも設定項目が多いですが、提供されるUIはより洗練されており、モダンなWindowsアプリケーションにはより適しています。ただし、NuGetパッケージの追加が必要であること、およびWindows XP以前のOSでは動作しない(FolderBrowserDialog
は古いスタイルで動作可能)という点に注意が必要です。
8. まとめ
この記事では、C#における標準的なフォルダ選択ダイアログであるFolderBrowserDialog
の使い方について、その基本的な利用方法から、主要なプロパティ、実践的なコード例、エラーハンドリング、そして代替手段であるCommonOpenFileDialog
との比較まで、詳細に解説しました。
FolderBrowserDialog
は、C#のWindows Formsアプリケーションでユーザーにフォルダを選択させるためのシンプルかつ効果的なツールです。using
ステートメントによる適切なリソース管理、Description
やSelectedPath
、RootFolder
といったプロパティによるカスタマイズ、そしてShowDialog()
メソッドの戻り値による結果判定が、基本的な使い方となります。特に、RootFolder
にEnvironment.SpecialFolder
列挙体を指定することで、ダイアログの開始位置を制御できる点は便利です。
また、ユーザーが「キャンセル」を選択した場合の処理や、SelectedPath
が有効なパスを含んでいるかの確認など、堅牢なアプリケーションを構築するためのエラーハンドリングや注意点も重要です。UIスレッド以外からの呼び出しにはInvoke
が必要となる点も覚えておくべきです。
さらに、Windows Vista以降のモダンなUIと豊富な機能を求める場合は、Microsoft.WindowsAPICodePack.Dialogs
ライブラリのCommonOpenFileDialog
という強力な代替手段があることも紹介しました。CommonOpenFileDialog
はNuGetパッケージの追加が必要ですが、IsFolderPicker = true
とするだけでフォルダ選択モードになり、より洗練されたユーザーエクスペリエンスを提供できます。
どちらのダイアログを選択するかは、アプリケーションの要件、対象とするOSバージョン、そして求められる機能によって異なります。シンプルなフォルダ選択であればFolderBrowserDialog
で十分ですが、モダンなUIや高度な機能を活用したい場合はCommonOpenFileDialog
が適しています。
この記事が、あなたのC#アプリケーション開発におけるフォルダ選択機能の実装に役立つことを願っています。適切なダイアログを選択し、ユーザーフレンドリーなアプリケーションを構築してください。