ディレクトリを開くダイアログ


274

次に生成するファイルを保存するディレクトリをユーザーに選択させたい。WPFではOpenFileDialogWin32のを使用する必要があることを知っていますが、残念ながらダイアログではファイルを選択する必要があります。ファイルを選択せず​​に単に[OK]をクリックすると、ファイルは開いたままになります。ユーザーにファイルを選択させ、パスを取り除いて、どのディレクトリに属しているかを確認することで、機能を「ハックアップ」することもできますが、直感的にはわかりません。誰かがこれを以前に行ったことを見たことがありますか?




回答:


406

これには、組み込みのFolderBrowserDialogクラスを使用できます。System.Windows.Forms名前空間にあることを気にしないでください。

using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
{
    System.Windows.Forms.DialogResult result = dialog.ShowDialog();
}

ウィンドウをWPFウィンドウ上でモーダルにする場合は、WPFアプリケーションからFolderBrowserDialogを使用する方法の質問を参照してください。


編集:プレーンで醜いWindowsフォームのFolderBrowserDialogよりも少し凝ったものが必要な場合は、代わりにVistaダイアログを使用できるいくつかの代替方法があります。

  • Ookiiダイアログなどのサードパーティライブラリ(.NET 3.5)
  • WindowsのAPIコードパック-シェル

    using Microsoft.WindowsAPICodePack.Dialogs;
    
    ...
    
    var dialog = new CommonOpenFileDialog();
    dialog.IsFolderPicker = true;
    CommonFileDialogResult result = dialog.ShowDialog();
    

    このダイアログは、Windows Vistaより古いオペレーティングシステムでは使用できないため、必ずCommonFileDialog.IsPlatformSupported最初に確認してください。


78
これはひどいダイアログであることに注意してください。パスをコピーしてそれに貼り付けることはできません。また、お気に入りのフォルダーはサポートされていません。全体として、私は5点満点で0にし、誰も使用しないことをお勧めします。Windows Vistaがはるかに優れたフォルダダイアログを表示するまで、妥当な代替手段がなかったことを除いて。Vista +では良いダイアログを表示する優れた無料のライブラリがあり、XPでは悪いライブラリを表示します。
Roman Starkov

70
それでも、WPFが優れたOpenFileDialogを提供するのにOpenFolderDialogを提供しないのはなぜですか?ちょっと変じゃないですか?ここにWPFがないのはなぜですか?WPFでこのダイアログのクラスを追加する計画はありますか?
Paul-Sebastian Manole 2013年

14
FolderBrowserDialogは使い捨てであることを忘れないでください。
LosManos 2014年

9
から使用するにはCommonOpenFileDialogWindowsAPICodePackする必要があることに注意してくださいInstall-Package WindowsAPICodePack-Shell。回答で提供されているリンクはそれをリストしていません。
Nikola Novak 14

5
「タイプまたは名前空間CommonOpenFileDialogが見つかりませんでした」。それは2017年で、フォルダーを
Nick.McDermaid

46

次のように使用されるUserControlを作成しました。

  <UtilitiesWPF:FolderEntry Text="{Binding Path=LogFolder}" Description="Folder for log files"/>

xamlソースは次のようになります。

<UserControl x:Class="Utilities.WPF.FolderEntry"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DockPanel>
        <Button Margin="0" Padding="0" DockPanel.Dock="Right" Width="Auto" Click="BrowseFolder">...</Button>
        <TextBox Height="Auto" HorizontalAlignment="Stretch" DockPanel.Dock="Right" 
           Text="{Binding Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
    </DockPanel>
</UserControl>

そしてコードビハインド

public partial class FolderEntry {
    public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(FolderEntry), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    public static DependencyProperty DescriptionProperty = DependencyProperty.Register("Description", typeof(string), typeof(FolderEntry), new PropertyMetadata(null));

    public string Text { get { return GetValue(TextProperty) as string; } set { SetValue(TextProperty, value); }}

    public string Description { get { return GetValue(DescriptionProperty) as string; } set { SetValue(DescriptionProperty, value); } }

    public FolderEntry() { InitializeComponent(); }

    private void BrowseFolder(object sender, RoutedEventArgs e) {
        using (FolderBrowserDialog dlg = new FolderBrowserDialog()) {
            dlg.Description = Description;
            dlg.SelectedPath = Text;
            dlg.ShowNewFolderButton = true;
            DialogResult result = dlg.ShowDialog();
            if (result == System.Windows.Forms.DialogResult.OK) {
                Text = dlg.SelectedPath;
                BindingExpression be = GetBindingExpression(TextProperty);
                if (be != null)
                    be.UpdateSource();
            }
        }
    }
 }

1
+ 1、UserControlの記述方法の良い例。1つの質問:なぜ必要なのbe.UpdateSourceですか?依存関係プロパティで通知を自動的に変更すべきではありませんか?
ハインツィ2009

4
更新をいつ起動するかをバインディングで指定できます。デフォルトではLostFocusにありますが、PropertyChangedでも更新を起動するように指示できます。
アレクサンドラ

3
その後、キーストロークごとにバインディングも更新されます。ユーザーが更新時に何らかの検証(Directory.Existなど)を行うと、問題が発生する可能性があります。
adrianm 2009


10

OokiiフォルダーダイアログはNugetにあります。

PM> Install-Package Ookii.Dialogs

また、サンプルコードは以下の通りです。

var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog();
if (dialog.ShowDialog(this).GetValueOrDefault())
{
    textBoxFolderPath.Text = dialog.SelectedPath;
}

tnxあなたの方法は最短だった
ehsan wwe

8

カスタムダイアログを作成したくないが、100%WPFの方法を好み、個別のDDL、追加の依存関係、または古いAPIを使用したくない場合は、[名前を付けて保存]ダイアログを使用して非常に簡単なハックを思いつきました。

usingディレクティブは必要ありません。以下のコードをコピーして貼り付けてください。

それはまだ非常にユーザーフレンドリーであり、ほとんどの人は気付かないでしょう。

この考え方は、ダイアログのタイトルを変更したり、ファイルを非表示にしたり、結果のファイル名を簡単に回避したりできるという事実に基づいています。

それは確かに大きなハックですが、多分それはあなたの使用法のためにうまくいくでしょう...

この例では、結果のパスを含むテキストボックスオブジェクトがありますが、必要に応じて関連する行を削除し、戻り値を使用できます...

// Create a "Save As" dialog for selecting a directory (HACK)
var dialog = new Microsoft.Win32.SaveFileDialog();
dialog.InitialDirectory = textbox.Text; // Use current value for initial dir
dialog.Title = "Select a Directory"; // instead of default "Save As"
dialog.Filter = "Directory|*.this.directory"; // Prevents displaying files
dialog.FileName = "select"; // Filename will then be "select.this.directory"
if (dialog.ShowDialog() == true) {
    string path = dialog.FileName;
    // Remove fake filename from resulting path
    path = path.Replace("\\select.this.directory", "");
    path = path.Replace(".this.directory", "");
    // If user has changed the filename, create the new directory
    if (!System.IO.Directory.Exists(path)) {
        System.IO.Directory.CreateDirectory(path);
    }
    // Our final value is in path
    textbox.Text = path;
}

このハックの唯一の問題は次のとおりです。

  • 確認ボタンには、まだ「ディレクトリを選択」などではなく「保存」と表示されていますが、鉱山のような場合は、ディレクトリの選択を「保存」して、引き続き機能します...
  • 入力フィールドには「ディレクトリ名」ではなく「ファイル名」と表示されますが、ディレクトリはファイルの一種と言えます...
  • 「ファイルの種類」ドロップダウンはまだありますが、その値は「ディレクトリ(* .this.directory)」と表示され、ユーザーはそれを他の何かに変更することはできず、私のために機能します...

ほとんどの人はこれらに気づかないでしょうが、マイクロソフトが頭を尻から出してくれるなら私は公式のWPFの方法を使用することを間違いなく好むでしょうが、そうするまで、それは私の一時的な修正です。


1
これはクールでした。誰もこれを試したことがないように思われることに驚いた。もちろん、NuGetパッケージの方がはるかに優れていますが、NuGet WindowsAPICodePackがないと、新しいパッケージや参照を追加せずにフォルダを選択する機能をハッキングする優れた方法です。
コード初心者

7

Directory Dialogがディレクトリパスを取得するには、まず参照System.Windows.Formsを追加し、次にResolveを実行してから、このコードをボタンのクリックに配置します。

    var dialog = new FolderBrowserDialog();
    dialog.ShowDialog();
    folderpathTB.Text = dialog.SelectedPath;

(folderpathTBはTextBoxの名前で、ここにフォルダーパスを入れます。または、uを文字列変数に割り当てることもできます)

    string folder = dialog.SelectedPath;

そして、あなたがファイル名/パスを取得したい場合は、ボタンクリックでこれを実行してください

    FileDialog fileDialog = new OpenFileDialog();
    fileDialog.ShowDialog();
    folderpathTB.Text = fileDialog.FileName;

(folderpathTBは、ファイルパスを配置するTextBoxの名前です。または、uを文字列変数に割り当てることもできます)

注:フォルダーダイアログの場合、System.Windows.Forms.dllをプロジェクトに追加する必要があります。追加しないと機能しません。


回答ありがとうございます。このアプローチはすでに上記の@Heinziで説明されています。
Alexandra

5

以下のリンクで以下のコードを見つけました...そしてそれは フォルダー選択ダイアログWPFを機能させました

using Microsoft.WindowsAPICodePack.Dialogs;

var dlg = new CommonOpenFileDialog();
dlg.Title = "My Title";
dlg.IsFolderPicker = true;
dlg.InitialDirectory = currentDirectory;

dlg.AddToMostRecentlyUsedList = false;
dlg.AllowNonFileSystemItems = false;
dlg.DefaultDirectory = currentDirectory;
dlg.EnsureFileExists = true;
dlg.EnsurePathExists = true;
dlg.EnsureReadOnly = false;
dlg.EnsureValidNames = true;
dlg.Multiselect = false;
dlg.ShowPlacesList = true;

if (dlg.ShowDialog() == CommonFileDialogResult.Ok) 
{
  var folder = dlg.FileName;
  // Do something with selected folder string
}

4

あなたが望むものを達成するための最良の方法は、あなた自身のWPFベースのコントロールを作成する
か、なぜ他の人によって作られたものを使用することですか?(何らかの理由で)wpfアプリケーションで winforms ダイアログを使用するとパフォーマンスに顕著な影響があるため、
このプロジェクトを推奨します
https://opendialog.codeplex.com/
またはNuget:

PM> Install-Package OpenDialog

それは非常にMVVMフレンドリーで、winformsダイアログをラップしていません


3

ナゲットパッケージに追加するには、次のようにします。

  Install-Package OpenDialog

それを使用する方法は次のとおりです:

    Gat.Controls.OpenDialogView openDialog = new Gat.Controls.OpenDialogView();
    Gat.Controls.OpenDialogViewModel vm = (Gat.Controls.OpenDialogViewModel)openDialog.DataContext;
    vm.IsDirectoryChooser = true;
    vm.Show();

    WPFLabel.Text = vm.SelectedFilePath.ToString();

ここにドキュメントがあります:http : //opendialog.codeplex.com/documentation

ファイル、フィルター付きファイル、フォルダーなどに対応


2

おおきいVistaFolderBrowserDialogはあなたが欲しいものです。

あなただけのフォルダブラウザたい場合は大木ダイアログと他には何をそれからソースをダウンロードし、フォルダブラウザ(ヒント:7つのファイル)に必要なファイルをチェリー選ぶと、それは、.NET 4.5.2で罰金を構築します。への参照を追加する必要がありましたSystem.Drawing。元のプロジェクトの参照を自分のプロジェクトと比較します。

どのファイルをどのようにして見つけますか?アプリとOokiiを別のVisual Studioインスタンスで開きます。VistaFolderBrowserDialog.csアプリに追加し、ビルドエラーがなくなるまでファイルを追加し続けます。Ookiiプロジェクトで依存関係を見つけます。Controlキーを押しながら、ソースにたどりたいもの(しゃれた意図)をクリックします。

これを行うのが面倒な場合に必要なファイルは次のとおりです...

NativeMethods.cs
SafeHandles.cs
VistaFolderBrowserDialog.cs
\ Interop
   COMGuids.cs
   ErrorHelper.cs
   ShellComInterfaces.cs
   ShellWrapperDefinitions.cs

197行目を編集しVistaFolderBrowserDialog.csたい場合は、Resources.Resx

新しいInvalidOperationException(Properties.Resources.FolderBrowserDialogNoRootFolder);をスローします。

throw new InvalidOperationException("Unable to retrieve the root folder.");

彼らの著作権通知をアプリに追加します license.txt

内のコード\Ookii.Dialogs.Wpf.Sample\MainWindow.xaml.cs行160から169には、使用できる例ですが、あなたは削除する必要がありますthis,から、MessageBox.Show(this,WPFのために。

自分のマシンで動作[TM]


2

私はこれが古い質問であることを知っていますが、これを行う簡単な方法は、WPFによって提供されるFileDialogオプションを使用し、System.IO.Path.GetDirectory(filename)を使用することです。


ただし、ユーザーはフォルダーを選択するように指示されている場合でも、ファイルを選択する必要があります。経験の浅いユーザーがこの時点で
HelpDeskを呼び出し

0

これらの答えはどれもうまくいきませんでした(一般に、参照が欠落しているか、それらの線に沿って何かがありました)

しかし、これは非常に単純です:

WPFアプリケーションでのFolderBrowserDialogの使用

参照を追加して、System.Windows.Formsこのコードを使用します。

  var dialog = new System.Windows.Forms.FolderBrowserDialog();
  System.Windows.Forms.DialogResult result = dialog.ShowDialog();

不足しているパッケージを追跡する必要はありません。または膨大なクラスを追加する

これにより、新しいフォルダーを作成できるモダンなフォルダーセレクターが表示されます

他のマシンに配置したときの影響はまだわかりません


0

このようなsmthをWPFで使用できます。メソッド例を作成しました。以下を確認してください。

public string getFolderPath()
{
           // Create OpenFileDialog 
           Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();

           OpenFileDialog openFileDialog = new OpenFileDialog();
           openFileDialog.Multiselect = false;

           openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
           if (openFileDialog.ShowDialog() == true)
           {
               System.IO.FileInfo fInfo = new System.IO.FileInfo(openFileDialog.FileName);
               return fInfo.DirectoryName;
           }
           return null;           
       }

1
これには、ユーザーがフォルダーからファイルを選択する必要があります。フォルダが空の場合は、フォルダを選択できません。
Alexandru Dicu 2018年

はい、わかりました。これは何らかの回避策であり、この問題の完全な解決策ではありません。
koberone
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.