it-swarm.com.de

Wählen Sie den Ordner-Dialog WPF

Ich entwickle eine WPF4-Anwendung und in meiner App muss ich den Benutzer einen Ordner auswählen, in dem die Anwendung etwas speichern wird (Dateien, generierte Berichte usw.).

Meine Anforderungen:

  • Möglichkeit zum Anzeigen der Standardordnerstruktur

  • Möglichkeit, einen Ordner auszuwählen

  • WPF-Look & Feel, dieser Dialog muss wie ein Teil einer modernen Anwendung aussehen, die für Windows Vista/7 und nicht für Windows 2000 oder Win9x entwickelt wurde.

Wie ich es verstehe, wird es bis 2010 (.Net 4.0) keinen Standardordner-Dialog geben, aber vielleicht gibt es einige Änderungen in Version 4.0?

Oder Sie brauchen nur den alten WinForms-Dialog zu verwenden. Wenn es die einzige Möglichkeit ist, das zu tun, was ich brauche, wie kann ich es dem Vista/7-Stil und nicht Win9x näher bringen?

In einigen Foren habe ich gesehen, wie solche Dialoge implementiert wurden, allerdings mit alten hässlichen Symbolen à la Windows 95. Es sieht wirklich nicht schön aus.

58
Mike B.

Ich habe darüber vor langer Zeit in meinem Blog darüber geschrieben, WPFs Unterstützung für allgemeine Dateidialoge ist wirklich schlecht (oder war zumindest in 3.5, dass ich Version 4 nicht eingecheckt habe) - aber es ist leicht zu umgehen.

Sie müssen der Anwendung das richtige Manifest hinzufügen. Dadurch erhalten Sie moderne Meldungsfelder und einen Ordner-Browser (WinForms FolderBrowserDialog), jedoch keine Dialogfelder zum Öffnen/Speichern von WPF-Dateien. Dies wird in diesen 3 Beiträgen beschrieben (wenn Sie dies nicht beachten über die Erklärung und will nur die Lösung direkt zum 3.):

Glücklicherweise sind die Dialoge zum Öffnen/Speichern sehr dünne Wrapper um die Win32-API, die einfach mit den richtigen Flags aufgerufen werden kann, um den Vista/7-Stil zu erhalten (nachdem das Manifest gesetzt wurde).

19
Nir

Windows Presentation Foundation 4.5 Cookbook von Pavel Yosifovich auf Seite 155 im Abschnitt "Verwenden der allgemeinen Dialogfelder" sagt:

"Was ist mit der Ordnerauswahl (anstelle von Dateien)? WPF OpenFileDialog unterstützt das nicht. Eine Lösung ist die Verwendung von Windows Forms 'FolderBrowseDialog-Klasse. Eine andere gute Lösung ist die Verwendung des .__ kurz beschrieben. "

Ich habe das API Code Pack von heruntergeladen Windows® API Code Pack für Microsoft® .NET Framework Windows API Code Pack: Wo ist es? , fügte dann meinem WPF 4.5-Projekt Verweise auf Microsoft.WindowsAPICodePack.dll und Microsoft.WindowsAPICodePack.Shell.dll hinzu. 

Beispiel:

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
}
93
T Powers

Fügen Sie Die Windows API Code Pack-Shell zu Ihrem Projekt hinzu

using Microsoft.WindowsAPICodePack.Dialogs;

...

var dialog = new CommonOpenFileDialog();
dialog.IsFolderPicker = true;
CommonFileDialogResult result = dialog.ShowDialog();
7
zeynab farzaneh

MVVM + WinForms FolderBrowserDialog als Verhalten

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

Verwendungszweck

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

Microsoft.Win32.OpenFileDialog ist der Standarddialog, den jede Anwendung unter Windows verwendet. Ihr Benutzer wird nicht überrascht sein, wenn Sie WPF in .NET 4.0 verwenden

Der Dialog wurde in Vista geändert. WPF in .NET 3.0 und 3.5 verwendeten noch den alten Dialog, der jedoch in .NET 4.0 behoben wurde. Ich kann nur vermuten, dass Sie diesen Thread gestartet haben, weil Sie diesen alten Dialog sehen. Dies bedeutet wahrscheinlich, dass Sie tatsächlich ein Programm ausführen, das auf 3.5 ausgerichtet ist. Ja, der Winforms-Wrapper did hat das Upgrade erhalten und zeigt die Vista-Version. System.Windows.Forms.OpenFileDialog-Klasse müssen Sie einen Verweis auf System.Windows.Forms hinzufügen. 

5
Hans Passant

Wenn Sie weder Windows Forms verwenden noch Manifest-Dateien bearbeiten möchten, habe ich mit dem WPAs-Dialogfeld "SaveAs" einen sehr einfachen Hack erstellt, um ein Verzeichnis auszuwählen. 

Keine using-Direktive erforderlich, Sie können einfach den folgenden Code kopieren und einfügen!

Es sollte immer noch sehr benutzerfreundlich sein und die meisten Leute werden es nie bemerken.

Die Idee kommt von der Tatsache, dass wir den Titel dieses Dialogs ändern, Dateien ausblenden und den resultierenden Dateinamen ziemlich leicht umgehen können. 

Es ist sicherlich ein großer Hack, aber vielleicht erledigt es die Arbeit gut für Ihren Einsatz ...

In diesem Beispiel habe ich ein Textfeldobjekt, das den resultierenden Pfad enthalten soll. Sie können jedoch die zugehörigen Zeilen entfernen und einen Rückgabewert verwenden, wenn Sie möchten ... 

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

Die einzigen Probleme mit diesem Hack sind:

  • Die Bestätigungsschaltfläche sagt immer noch "Speichern" anstelle von "Verzeichnis auswählen", aber in einem Fall wie "Minen" "Speichern" Sie die Verzeichnisauswahl, damit es immer noch funktioniert ... 
  • Das Eingabefeld sagt immer noch "Dateiname" anstelle von "Verzeichnisname", aber wir können sagen, dass ein Verzeichnis ein Dateityp ist ... 
  • Es gibt immer noch eine Dropdown-Liste "Dateityp", aber der Wert besagt "Directory (* .this.directory)", und der Benutzer kann es nicht ändern. 

Die meisten Leute werden dies nicht bemerken, obwohl ich es definitiv vorziehen würde, eine offizielle WPF-Methode zu verwenden, wenn sich Microsoft die Köpfe aus den Ärschen holen würde, aber bis dahin ist dies meine vorübergehende Lösung. 

3
Olivier St-L

Basierend auf der Antwort von Oyun ist es besser, eine Abhängigkeitseigenschaft für den Ordnernamen zu verwenden. Dies ermöglicht (z. B.) das Binden von Untereigenschaften, was im Original nicht funktioniert. In meiner angepassten Version zeigt das Dialogfeld auch den ursprünglichen Ordner an.

Verwendung in XAML:

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

Code: 

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
Edward

Die Ookii-Dialoge für WPF haben eine VistaFolderBrowserDialog-Klasse, die eine vollständige Implementierung eines Ordnerbrowserdialogs für WPF ermöglicht.

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

 enter image description here

Es gibt auch eine Version, die mit Windows Forms funktioniert.

1
Caio Proiete

Nur dieser Dialog ist FileDialog . Es ist Teil von WinForms, aber es ist eigentlich nur ein Wrapper für den WinAPI-Standard-OS-Dateidialog. Und ich denke nicht, dass es hässlich ist, es ist eigentlich ein Teil des Betriebssystems, also sieht es aus, als würde es laufen.

Auf andere Weise gibt es nichts, was Ihnen helfen könnte. Sie müssen entweder nach einer Drittanbieter-Implementierung suchen, entweder kostenlos (und ich glaube nicht, dass es etwas Gutes gibt) oder bezahlt.

0
Euphoric