디렉토리 열기 대화 상자


274

사용자가 생성 할 파일이 저장 될 디렉토리를 선택하기를 원합니다. WPF OpenFileDialog에서 from Win32를 사용해야한다는 것을 알고 있지만 불행히도 대화 상자에는 파일을 선택해야합니다. 하나를 선택하지 않고 확인을 클릭하면 열린 상태로 유지됩니다. 사용자가 파일을 선택한 다음 경로를 제거하여 파일이 속한 디렉토리를 알아낼 수는 있지만 직관적이지 않습니다. 이 일을 전에 본 사람이 있습니까?




답변:


406

이를 위해 내장 FolderBrowserDialog 클래스를 사용할 수 있습니다 . System.Windows.Forms네임 스페이스 에 있다는 것을 신경 쓰지 마십시오 .

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

창을 일부 WPF 창에서 모달로 표시하려면 WPF 응용 프로그램에서 FolderBrowserDialog를 사용하는 방법 질문을 참조하십시오 .


편집 : 일반, 추악한 Windows Forms FolderBrowserDialog보다 조금 더 멋진 것을 원한다면 대신 Vista 대화 상자를 사용할 수있는 몇 가지 대안이 있습니다.

  • Ookii 대화 상자 와 같은 타사 라이브러리 (.NET 3.5)
  • 윈도우 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가 훨씬 더 나은 폴더 대화 상자를 제공 하기 전까지는 합리적인 대안이 없었습니다 . 있다 좋은 무료 라이브러리 비스타 +에 좋은 대화 및 XP에 나쁜 일을 보여줍니다.
Roman Starkov

70
여전히 WPF는 왜 OpenFolderDialog가없는 훌륭한 OpenFileDialog를 제공합니까? 조금 이상하지 않습니까? 왜 WPF가 부족합니까? WPF에서이 대화 상자에 대한 클래스를 추가 할 계획이 있습니까?
Paul-Sebastian Manole

14
FolderBrowserDialog는 일회용이라는 것을 잊지 마십시오.
LosManos

9
사용하기 위해서는주의 CommonOpenFileDialog에서 WindowsAPICodePack당신이 필요합니다 Install-Package WindowsAPICodePack-Shell. 답변에 제공된 링크에는 해당 링크가 없습니다.
Nikola Novak

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 작성 방법에 대한 좋은 예입니다. 한 가지 질문 : 왜 필요한 be.UpdateSource가요? 종속성 속성에서 알림을 자동으로 변경해서는 안됩니까?
Heinzi

4
바인딩을 업데이트 할시기를 지정할 수 있습니다. 기본적으로 LostFocus에 있지만 PropertyChanged에서도 업데이트를 실행하도록 지시 할 수 있습니다.
Alexandra

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 당신의 방법은 짧은이었다
에산 WWE

8

사용자 정의 대화 상자를 만들지 않고 100 % WPF 방식을 선호하고 별도의 DDL, 추가 종속성 또는 오래된 API를 사용하지 않으려는 경우 다른 이름으로 저장 대화 상자를 사용하여 매우 간단한 해킹을 생각해 냈습니다.

사용 지시문이 필요하지 않으므로 아래 코드를 복사하여 붙여 넣을 수 있습니다!

여전히 매우 사용자 친화적이어야하며 대부분의 사람들은 눈치 채지 못할 것입니다.

아이디어는 대화 상자의 제목을 변경하고 파일을 숨기고 결과 파일 이름을 매우 쉽게 해결할 수 있다는 사실에서 비롯됩니다.

확실히 큰 해킹이지만 어쩌면 사용법에 따라 잘 작동 할 것입니다 ...

이 예제에서는 결과 경로를 포함하는 텍스트 상자 객체가 있지만 원하는 경우 관련 줄을 제거하고 반환 값을 사용할 수 있습니다.

// 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

디렉터리 대화 상자에서 디렉터리 경로를 얻으려면 먼저 참조 System.Windows.Forms를 추가 한 다음 확인을 클릭 한 다음이 코드를 단추 클릭으로 넣습니다.

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

(folderpathTB는 폴더 경로를 넣고 싶어하는 TextBox의 이름입니다. 또는 문자열 변수에도 할당 할 수 있습니다)

    string folder = dialog.SelectedPath;

FileName / path를 얻으려면 버튼 클릭으로 간단히 수행하십시오.

    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

Ookii VistaFolderBrowserDialog는 당신이 원하는 것입니다.

Ooki 대화 상자 의 폴더 브라우저 만 원하고 소스다운로드 하지 않으면 폴더 브라우저에 필요한 파일 (힌트 : 7 파일)을 선택하고 .NET 4.5.2에서 올바르게 빌드하십시오. 에 대한 참조를 추가해야했습니다 System.Drawing. 원래 프로젝트의 참조를 귀하의 참조와 비교하십시오.

어떤 파일을 어떻게 알 수 있습니까? 다른 Visual Studio 인스턴스에서 앱과 Ookii를 엽니 다. 추가 VistaFolderBrowserDialog.cs앱과 빌드 오류가 사라질 때까지 추가 파일을 보관. Ookii 프로젝트에서 종속성을 찾으십시오-Control- 클릭하십시오.

너무 게으른 경우 필요한 파일은 다음과 같습니다.

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

VistaFolderBrowserDialog.cs포함하지 않으려면 197 행을 편집하십시오.Resources.Resx

새로운 InvalidOperationException을 던집니다 (Properties.Resources.FolderBrowserDialogNoRootFolder);

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

앱에 따라 저작권 표시를 앱에 추가하십시오. license.txt

\Ookii.Dialogs.Wpf.Sample\MainWindow.xaml.cs160-169 행 의 코드 는 사용할 수있는 예제이지만 WPF this,에서 제거해야합니다 MessageBox.Show(this,.

내 컴퓨터에서 작동 [TM]


2

나는 이것이 오래된 질문이라는 것을 알고 있지만 이것을하는 간단한 방법은 WPF가 제공하고 System.IO.Path.GetDirectory (filename)를 사용하는 FileDialog 옵션을 사용하는 것입니다.


그러나 사용자는 폴더를 선택하라는 메시지가 표시 되더라도 파일을 선택해야합니다. 경험이없는 사용자는이 시점에서 HelpDesk를 호출하여 폴더를 선택해야 할 때 파일을 선택
해야하는 이유를 묻습니다.

0

이 답변 중 어느 것도 나를 위해 일하지 않았습니다 (일반적으로 누락 된 참조 또는 그 줄을 따라 뭔가가있었습니다)

그러나 이것은 매우 간단했습니다.

WPF 응용 프로그램에서 FolderBrowserDialog 사용

System.Windows.Forms이 코드에 대한 참조를 추가 하고 사용하십시오.

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

누락 된 패키지를 추적 할 필요가 없습니다. 또는 거대한 수업을 추가하십시오

이것은 나에게 새로운 폴더를 만들 수있는 현대적인 폴더 선택기를 제공합니다.

다른 컴퓨터에 배포 할 때의 영향을 아직 보지 못했습니다


0

WPF에서 이와 같이 smth를 사용할 수 있습니다. 예제 방법을 만들었습니다. 아래를 확인하십시오.

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

그렇습니다.이 문제에 대한 완벽한 해결책이 아니라 일종의 해결 방법이라는 것을 알고 있습니다.
koberone
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.