こんにちは、働くC#プログラマーのさんさめです。
複数のファイルを一括で出力したいときなど、
ユーザーにフォルダを選択して欲しいことはままあります。
WPFで、フォルダ選択ダイアログを使おうとすると、
いくつか選択肢がありますが、
使いやすさを考えると、事実上一択です。
ずばり、
WindowsAPICodePack-Shellをnuget参照して、
CommonOpenFileDialogクラスを使うのがベストです。
というわけで本記事では、
WPFで採用できるフォルダ選択ダイアログの種類と、
その特徴、および、
なぜCommonOpenFileDialogを
使うべきかについて解説します。
フォルダ選択ダイアログの種類
WPFでWindows組み込みのフォルダ選択ダイアログを出すには、
大きく分けて3つの方法があります。
- FolderBrowserDialog
- OpenFileDialog
- CommonOpenFileDialog
それぞれ詳しく見ていきます。
FolderBrowserDialog
WPFでもっとも簡単にフォルダ選択ダイアログを使うならば、
System.Windows.Forms名前空間にある、
FolderBrowserDialogがあります。
これは、参照を追加する必要があります。
といっても、VisualStudioならば、
おもむろにFolderBrowserDialogと入力して
「Ctrl+.」を押せば自動で参照の追加とusingを行ってくれますね。
使い方のサンプルは以下のコードを見てください。
using (var fbd = new FolderBrowserDialog()
{
Description = "フォルダを選択してください",
SelectedPath = @"D:\Users\threeshark",
})
{
// OKが押されずに終わった場合はキャンセルされている
if (fbd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
{
return;
}
// SelectedPathで選択されたフォルダを取得する
System.Windows.MessageBox.Show($"{fbd.SelectedPath}を選択しました");
}
実行すると、
次のような見た目のダイアログが出ます。
どうでしょう。そんなに悪い感じもしませんね。
ところが、何度もフォルダ選択が必要なアプリケーションでは、
このダイアログの使い勝手の悪さが目立ってきます。
具体的には
- ツリーの展開状況が記憶されないので、
毎回展開していく必要がある - パスを入力する欄が無くジャンプできない
- 「クイックアクセス」が表示されない
といったことが挙げられます。
OpenFileDialog
次は、ファイル選択ダイアログでおなじみ、
OpenFileDialogです。
名前空間がSystem.Windows.Formsのものと、
Microsoft.Win32のものがありますが、
使い勝手はほぼ同じものとなっております。
使い方は以下のサンプルコードの通り…
なんですが、実はOpenFileDialogには致命的な問題があります。
var ofd = new Microsoft.Win32.OpenFileDialog()
{
Title = "フォルダを選択してください",
InitialDirectory = @"D:\Users\threeshark",
Filter = "Folder|.",
CheckFileExists = false,
};
// OKが押されずに終わった場合はfalseかnullが返る
if (ofd.ShowDialog() != true)
{
return;
}
// FileNameで選択されたフォルダを取得したい…のだが、
// そもそもフォルダを選んでOKを押しても
// その中に移動するだけで確定されない
System.Windows.MessageBox.Show($"{ofd.FileName}を選択しました");
そう、OpenFileDialogでは、そもそも
既存フォルダを選択して確定することができないのです。
実行して実際に選択しようとしてOKを押すと、
なんとそのフォルダの中に入ってしまいます。
というわけで、
大きく分けて3つの方法があると言っておいて、
実はこの方法は使えないんですね。
ただ、ファイルを選択する分には、
OpenFileDialogは普通に使えます。
CommonOpenFileDialog
さて、満を持して紹介するのが、
CommonOpenFileDialogです。
これは、nugetからWindowsAPICodePack-Shellを
インストールして参照に追加する必要があります。
似た名前のものがいくつかありますが、
どれを使っても大体同じ使い勝手のクラスが入っています。
こちらは、ちゃんとフォルダを選択する専用のモードがあります。
使い方は以下のコードのようになります。
using (var cofd = new CommonOpenFileDialog()
{
Title = "フォルダを選択してください",
InitialDirectory = @"D:\Users\threeshark",
// フォルダ選択モードにする
IsFolderPicker = true,
})
{
if (cofd.ShowDialog() != CommonFileDialogResult.Ok)
{
return;
}
// FileNameで選択されたフォルダを取得する
System.Windows.MessageBox.Show($"{cofd.FileName}を選択しました");
}
IsFolderPickerプロパティをtrueにすることで、
フォルダ選択モードにできます。
実行結果は以下のようになります。
先ほどのOpenFileDialogでは、「開く」
だったボタンが「フォルダーの選択」になっていますね。
CommonOpenFileDialogでは、
先ほどFolderBrowserDialogで挙げた、
- パスを入力する欄が無くジャンプできない
- 「クイックアクセス」が表示されない
といったデメリットがありません。
いわゆるエクスプローラーとほぼ同じ操作感覚で、
任意のフォルダを選んでもらうことができます。
また、InitialDirectoryを指定せずに、
RestoreDirectoryプロパティをtrueにしておくことで、
次回呼出し時に、
ユーザーが最後に選択したフォルダから始めることができます。
var cofd = new CommonOpenFileDialog()
{
Title = "フォルダを選択してください",
// 最後に選択したフォルダから始まる
RestoreDirectory = true,
IsFolderPicker = true,
}
まとめ
まとめです。
- WPFでフォルダ選択ダイアログを出すには
2つの選択肢がある - FolderBrowserDialogはややお手軽だが
使い勝手に難あり - CommonOpenFileDialogを
使った方が便利で気が利いている
最後までお読みいただき、ありがとうございました。
コメント
質問です。
このパッケージをインストールして利用しました。
メニュー(menustrip)から呼び出したのですが、
クリックして選択フォルダが開いた途端、
元のウインドウがフォント、ウインドウ共に小さくなってしまいました。
何か解決方法をご存知でしょうか。