Okno dialogowe wyboru folderu WPF

Rozwijam aplikację WPF4 i w mojej aplikacji muszę pozwolić użytkownikowi wybrać folder, w którym aplikacja będzie coś przechowywać (pliki, generowane raporty itp.).

Moje wymagania:

  • Możliwość wyświetlenia standardowego drzewa katalogów

  • Możliwość wyboru folderu

  • WPF look & feel, to okno dialogowe musi wyglądać jak część nowoczesnej aplikacji zaprojektowanej dla systemu Windows Vista / 7, a nie Windows 2000 lub nawet Win9x.

As I rozumiem, że do 2010 roku (. Net 4.0) nie będzie standardowego okna dialogowego folderów, ale może w wersji 4.0 będą jakieś zmiany?

Czy wystarczy użyć starego okna WinForms? Jeśli jest to jedyny sposób, aby zrobić to, czego potrzebuję, jak Mogę zbliżyć go do stylu Vista / 7, a nie Win9x?

Na niektórych forach widziałem implementację takich dialogów, ale ze starymi brzydkimi ikonami a la Windows 95. To naprawdę nie wygląda ładnie.

Author: Mike B., 2010-10-24

9 answers

Pisałem o tym na moim blogu dawno temu, obsługa WPF dla common file dialogów jest naprawdę zła ( a przynajmniej jest w 3.5 nie sprawdzałem w wersji 4) - ale łatwo to obejść.

Musisz dodać prawidłowy manifest do aplikacji - który da ci nowoczesne pola wiadomości i przeglądarkę folderów (WinForms FolderBrowserDialog), ale nie okno dialogowe otwierania/zapisywania pliku WPF, jest to opisane w tych 3 postach (jeśli nie dbasz o wyjaśnienie i chcesz tylko otworzyć plik WPF). rozwiązanie przejść bezpośrednio do 3):

Na szczęście okna dialogowe Otwórz / Zapisz są bardzo cienkimi opakowaniami wokół API Win32, które można łatwo wywołać z odpowiednimi flagami, aby uzyskać styl Vista / 7 (po ustawieniu manifestu)

 18
Author: Nir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-24 15:18:01

Windows Presentation Foundation 4.5 Cookbook by Pavel Yosifovich on page 155 in the section on "Using the common dialog boxes" says:

"A co z wyborem folderów (zamiast plików)? WPF OpenFileDialog tego nie obsługuje. Jednym z rozwiązań jest użycie systemu Windows Form "Folderbrows". Innym dobrym rozwiązaniem jest użycie Windows API Code Pack opisany krótko."

Pobrałem Pakiet kodu API z Kod Windows ® API Pakiet dla Microsoft®. NET Framework Windows API Code Pack: gdzie to jest?, następnie dodano odniesienia do Microsoft.WindowsAPICodePack.dll i Microsoft.WindowsAPICodePack.Shell.dll do mojego projektu WPF 4.5.

Przykład:

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
}
 91
Author: T Powers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:53

Dodaj Windows API Code Pack-Shell do swojego projektu

using Microsoft.WindowsAPICodePack.Dialogs;

...

var dialog = new CommonOpenFileDialog();
dialog.IsFolderPicker = true;
CommonFileDialogResult result = dialog.ShowDialog();
 6
Author: zeynab farzaneh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-23 13:53:33

Microsoft.Win32.OpenFileDialog jest standardowym oknem dialogowym używanym przez dowolną aplikację w systemie Windows. Twój użytkownik nie będzie zaskoczony jego wyglądem, gdy używasz WPF w. NET 4.0

Okno dialogowe zostało zmienione w Vista. WPF w. NET 3.0 i 3.5 nadal używało starszego okna dialogowego, ale zostało to naprawione w. NET 4.0. Mogę się tylko domyślać, że zacząłeś ten wątek, ponieważ widzisz to stare okno dialogowe. Co prawdopodobnie oznacza, że uruchamiasz program, który celuje w 3.5. Tak, Opakowanie Winforms Czy dostał upgrade i pokazuje wersję Vista. System.Okna.Formularze.Klasy OpenFileDialog, musisz dodać odniesienie do systemu.Okna.Formularze.

 5
Author: Hans Passant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-24 11:43:58

MVVM + WinForms FolderBrowserDialog jako zachowanie

public class FolderDialogBehavior : Behavior<Button>
{
    public string SetterName { get; set; }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Click += OnClick;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.Click -= OnClick;
    }

    private void OnClick(object sender, RoutedEventArgs e)
    {
        var dialog = new FolderBrowserDialog();
        var result = dialog.ShowDialog();
        if (result == DialogResult.OK && AssociatedObject.DataContext != null)
        {
            var propertyInfo = AssociatedObject.DataContext.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)
            .Where(p => p.CanRead && p.CanWrite)
            .Where(p => p.Name.Equals(SetterName))
            .First();

            propertyInfo.SetValue(AssociatedObject.DataContext, dialog.SelectedPath, null);
        }
    }
}

Użycie

     <Button Grid.Column="3" Content="...">
            <Interactivity:Interaction.Behaviors>
                <Behavior:FolderDialogBehavior SetterName="SomeFolderPathPropertyName"/>
            </Interactivity:Interaction.Behaviors>
     </Button>

Blogpost: http://kostylizm.blogspot.ru/2014/03/wpf-mvvm-and-winforms-folder-dialog-how.html

 5
Author: Oyun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-04 13:37:25

Bazując na odpowiedzi oyuna, lepiej jest użyć właściwości zależności dla nazwy folderu. Umożliwia to (na przykład) powiązanie z pod-właściwościami, które nie działają w oryginale. Również w mojej dostosowanej wersji okno dialogowe pokazuje wybór folderu początkowego.

Użycie w XAML:

<Button Content="...">
   <i:Interaction.Behaviors>
      <Behavior:FolderDialogBehavior FolderName="{Binding FolderPathPropertyName, Mode=TwoWay}"/>
    </i:Interaction.Behaviors>
</Button>

Kod:

using System.Windows;
using System.Windows.Forms;
using System.Windows.Interactivity;
using Button = System.Windows.Controls.Button;

public class FolderDialogBehavior : Behavior<Button>
{
    #region Attached Behavior wiring
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Click += OnClick;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.Click -= OnClick;
        base.OnDetaching();
    }
    #endregion

    #region FolderName Dependency Property
    public static readonly DependencyProperty FolderName =
            DependencyProperty.RegisterAttached("FolderName",
            typeof(string), typeof(FolderDialogBehavior));

    public static string GetFolderName(DependencyObject obj)
    {
        return (string)obj.GetValue(FolderName);
    }

    public static void SetFolderName(DependencyObject obj, string value)
    {
        obj.SetValue(FolderName, value);
    }
    #endregion

    private void OnClick(object sender, RoutedEventArgs e)
    {
        var dialog = new FolderBrowserDialog();
        var currentPath = GetValue(FolderName) as string;
        dialog.SelectedPath = currentPath;
        var result = dialog.ShowDialog();
        if (result == DialogResult.OK)
        {
            SetValue(FolderName, dialog.SelectedPath);
        }
    }
}
 2
Author: Edward,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-09 15:13:41

Jeśli nie chcesz używać Windows Forms ani edytować plików manifestu, wymyśliłem bardzo prosty hack przy użyciu okna dialogowego SaveAs WPF do wyboru katalogu.

Nie wymaga użycia dyrektywy, możesz po prostu skopiować i wkleić poniższy kod !

Nadal powinien być bardzo przyjazny dla użytkownika i większość ludzi nigdy nie zauważy.

Pomysł wynika z faktu, że możemy zmienić tytuł tego okna dialogowego, ukryć pliki i dość łatwo obejść wynikową nazwę pliku.

It jest duży hack na pewno, ale może to zrobić zadanie dobrze dla użytkownika...

W tym przykładzie mam obiekt textbox, który zawiera wynikową ścieżkę, ale możesz usunąć powiązane linie i użyć zwracanej wartości, jeśli chcesz...

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

Jedyne problemy z tym hackiem to:

  • przycisk Potwierdź nadal mówi " Zapisz "zamiast czegoś takiego jak "Wybierz katalog", ale w przypadku takim jak mines "Zapisz" wybór katalogu, więc nadal działa...
  • Wejście pole nadal mówi "nazwa pliku" zamiast "nazwa katalogu" , ale możemy powiedzieć, że katalog jest typem pliku...
  • nadal jest rozwijane "Zapisz jako typ" , ale jego wartość mówi " Katalog (*.to.Katalog)", a użytkownik nie może go zmienić na coś innego, działa dla mnie...

Większość ludzi tego nie zauważy, chociaż zdecydowanie wolałbym używać oficjalnego sposobu WPF, jeśli microsoft wyciągnie im głowy z tyłków, ale dopóki tego nie zrobią, to moja tymczasowa poprawka.

 2
Author: Olivier St-L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-09 20:54:35

Okna dialogowe Ookii dla WPF mają klasę VistaFolderBrowserDialog, która zapewnia pełną implementację okna dialogowego przeglądarki folderów dla WPF.

Https://github.com/caioproiete/ookii-dialogs-wpf

Tutaj wpisz opis obrazka

Istnieje również wersja, która działa z Windows Forms .

 1
Author: Caio Proiete,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 03:32:25

Jedynym takim oknem jest FileDialog . Jest częścią WinForms, ale w rzeczywistości tylko owija się wokół standardowego okna dialogowego pliku systemu operacyjnego WinAPI. I nie sądzę, że jest brzydki, jego faktycznie część OS, więc wygląda jak OS, na którym jest uruchomiony.

W inny sposób, nie ma w czym Ci pomóc. Albo trzeba szukać 3rd party implementacji, albo za darmo (i nie sądzę, że są jakieś dobre) lub płatne.

 0
Author: Euphoric,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-03 09:06:55