Диалог открытия каталога - PullRequest
250 голосов
/ 17 декабря 2009

Я хочу, чтобы пользователь выбрал каталог, в который будет сохранен файл, который я сгенерирую. Я знаю, что в WPF я должен использовать OpenFileDialog из Win32, но, к сожалению, диалог требует выбора файла (ов) - он остается открытым, если я просто нажму OK, не выбрав один. Я мог бы «взломать» функциональность, позволив пользователю выбрать файл, а затем лишить путь, чтобы выяснить, к какому каталогу он принадлежит, но в лучшем случае это не интуитивно понятно. Кто-нибудь видел это сделано раньше?

Ответы [ 13 ]

372 голосов
/ 17 декабря 2009

Для этого вы можете использовать встроенный класс FolderBrowserDialog . Не обращайте внимания, что он находится в пространстве имен System.Windows.Forms.

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

Если вы хотите, чтобы окно было модальным по сравнению с некоторым окном WPF, см. Вопрос Как использовать FolderBrowserDialog из приложения WPF .


РЕДАКТИРОВАТЬ: Если вы хотите что-то более изящное, чем простой, уродливый Windows Forms FolderBrowserDialog, есть несколько альтернатив, которые позволяют вам вместо этого использовать диалог Vista:

  • Сторонние библиотеки, такие как Диалоги Ookii (.NET 3.5)
  • Пакет оболочки Windows API Code :

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

    Обратите внимание, что это диалоговое окно недоступно в операционных системах, более старых, чем Windows Vista, поэтому сначала обязательно проверьте CommonFileDialog.IsPlatformSupported.

40 голосов
/ 17 декабря 2009

Я создал 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();
            }
        }
    }
 }
9 голосов
/ 10 апреля 2014

Я использую Ookii диалоги , и это хорошо работает для WPF.

Вот прямая страница:

http://www.ookii.org/Blog/new_download_ookiidialogs

7 голосов
/ 09 мая 2018

Для тех, кто не хочет создавать настраиваемое диалоговое окно, но все же предпочитает 100% WPF-способ и не хочет использовать отдельные DDL, дополнительные зависимости или устаревшие API, я предложил очень простой взлом с помощью Save Как диалог.

Использование директивы не требуется, вы можете просто скопировать и вставить приведенный ниже код!

Это все еще должно быть очень удобно, и большинство людей никогда не заметят.

Идея исходит из того факта, что мы можем легко изменить заголовок этого диалога, скрыть файлы и обойти полученное имя файла.

Это большой взлом, но, возможно, он отлично подойдет для вашего использования ...

В этом примере у меня есть объект текстового поля, в котором содержится результирующий путь, но вы можете удалить связанные строки и использовать возвращаемое значение, если хотите ...

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

Единственные проблемы с этим хаком:

  • Кнопка подтверждения по-прежнему говорит «Сохранить» вместо чего-то вроде «Выбрать каталог», но в случае, например мины, я «Сохранить» выбор каталога, чтобы он все еще работал ...
  • Поле ввода по-прежнему говорит «Имя файла» вместо «Имя каталога», но мы можем сказать, что каталог - это тип файла ...
  • Все еще есть выпадающий список "Сохранить как тип", но его значение говорит "Directory (* .this.directory)", и пользователь не может изменить его на что-то другое, у меня работает ...

Большинство людей этого не заметят, хотя я бы определенно предпочел использовать официальный способ WPF, если бы Майкрософт вытащил свои головы из задниц, но пока они этого не сделают, это мое временное исправление.

6 голосов
/ 05 января 2016

Диалог папки Ookii можно найти на Nuget.

PM> Install-Package Ookii.Dialogs

И, пример кода, как показано ниже.

var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog();
if (dialog.ShowDialog(this).GetValueOrDefault())
{
    textBoxFolderPath.Text = dialog.SelectedPath;
}
6 голосов
/ 07 ноября 2015

Чтобы в диалоге каталогов получить путь к каталогу, сначала добавьте ссылку System.Windows.Forms, а затем Resolve, а затем вставьте этот код одним нажатием кнопки.

    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, в которое я хочу поместить путь к файлу, ИЛИ вы также можете присвоить его строковой переменной)

Примечание. Для диалога папок в проект необходимо добавить файл System.Windows.Forms.dll, иначе он не будет работать.

4 голосов
/ 04 марта 2016

Я нашел код ниже по ссылке ниже ... и это сработало Диалог выбора папки 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 голосов
/ 12 июля 2015

Лучший способ достичь желаемого - создать собственный элемент управления на основе wpf или использовать тот, который был создан другими людьми
Зачем ? поскольку при использовании диалогового окна winforms в приложении wpf (по некоторым причинам) будет заметно снижаться производительность
я рекомендую этот проект
https://opendialog.codeplex.com/
или Nuget:

PM> Install-Package OpenDialog

это очень дружественно к MVVM и не переносит диалоговое окно winforms

3 голосов
/ 17 июня 2016

Я бы предложил добавить в пакет самородков:

  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 голосов
/ 14 сентября 2017

Я знаю, что это старый вопрос, но простой способ сделать это - использовать параметр FileDialog, предоставленный WPF, и использовать System.IO.Path.GetDirectory (имя файла).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...