Ich entwickle eine WPF4-Anwendung und muss in meiner App den Benutzer einen Ordner auswählen lassen, in dem die Anwendung etwas speichern wird (Dateien, generierte Berichte usw.).
Meine Anforderungen:
Möglichkeit, den Standardordnerbaum anzuzeigen
Möglichkeit, einen Ordner auszuwählen
WPF Look & Feel, dieser Dialog muss Teil einer modernen Anwendung sein, die für Windows Vista / 7 entwickelt wurde und nicht für Windows 2000 oder sogar Win9x.
Soweit ich weiß, wird es bis 2010 (.Net 4.0) keinen Standardordner-Dialog geben, aber vielleicht gibt es einige Änderungen in Version 4.0?
Oder müssen Sie nur den WinForms-Dialog der alten Schule verwenden? Wenn es der einzige Weg ist, das zu tun, was ich brauche, wie kann ich es dem Vista / 7-Stil näher bringen und nicht Win9x?
In einigen Foren habe ich die Implementierung solcher Dialoge gesehen, aber mit alten hässlichen Symbolen à la Windows 95. Es sieht wirklich nicht gut aus.
quelle
Antworten:
Ich habe vor langer Zeit in meinem Blog darüber geschrieben. Die Unterstützung von WPF für allgemeine Dateidialoge ist wirklich schlecht (oder zumindest in Version 3.5, die ich in Version 4 nicht eingecheckt habe) - aber es ist einfach, das zu umgehen.
Sie müssen Ihrer Anwendung das richtige Manifest hinzufügen. Dadurch erhalten Sie ein modernes Meldungsfeld und einen Ordnerbrowser (WinForms FolderBrowserDialog), jedoch keine Dialogfelder zum Öffnen / Speichern von WPF-Dateien. Dies wird in diesen drei Beiträgen beschrieben (wenn Sie sich nicht darum kümmern) über die Erklärung und möchte nur die Lösung direkt zum 3. gehen):
Glücklicherweise sind die Dialogfelder zum Öffnen / Speichern sehr dünne Wrapper um die Win32-API, die einfach mit den richtigen Flags aufgerufen werden können, um den Vista / 7-Stil zu erhalten (nach dem Festlegen des Manifests).
quelle
Das Windows Presentation Foundation 4.5-Kochbuch von Pavel Yosifovich auf Seite 155 im Abschnitt "Verwenden der allgemeinen Dialogfelder" lautet:
Ich habe das API-
Codepaketaus demWindows® API-Codepaket für Microsoft® .NET Frameworkheruntergeladen. Windows-API-Codepaket: Wo ist es?und 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 }
quelle
CommonOpenFileDialog
wurde aber nicht erkannt. (Ja, ich habe dasusing
eingegeben).Fügen Sie Ihrem Projekt die Windows API Code Pack-Shell hinzu
using Microsoft.WindowsAPICodePack.Dialogs; ... var dialog = new CommonOpenFileDialog(); dialog.IsFolderPicker = true; CommonFileDialogResult result = dialog.ShowDialog();
quelle
Wenn Sie weder Windows Forms verwenden noch Manifestdateien bearbeiten möchten, habe ich mir einen sehr einfachen Hack über das SaveAs-Dialogfeld von WPF ausgedacht, um tatsächlich ein Verzeichnis auszuwählen.
Keine Verwendung der 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 Dialogfelds ändern, Dateien ausblenden und den resultierenden Dateinamen ganz einfach umgehen können.
Es ist sicher ein großer Hack, aber vielleicht macht es den Job gut für Ihren Gebrauch ...
In diesem Beispiel habe ich ein Textfeldobjekt, das den resultierenden Pfad enthält, aber Sie können 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 meisten Leute werden dies nicht bemerken, obwohl ich es definitiv vorziehen würde, einen offiziellen WPF-Weg zu verwenden, wenn Microsoft ihre Köpfe aus ihren Ärschen bekommen würde, aber bis sie es tun, ist das meine vorübergehende Lösung.
quelle
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); } } }
Verwendung
<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
quelle
Microsoft.Win32.OpenFileDialog ist der Standarddialog, den jede Anwendung unter Windows verwendet. Ihr Benutzer wird von seinem Erscheinungsbild 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 verwendete weiterhin das alte Dialogfeld, das jedoch in .NET 4.0 behoben wurde. Ich kann nur vermuten, dass Sie diesen Thread gestartet haben, weil Sie diesen alten Dialog sehen. Was wahrscheinlich bedeutet, dass Sie tatsächlich ein Programm ausführen, das auf 3.5 abzielt. Ja, der Winforms-Wrapper hat das Upgrade erhalten und zeigt die Vista-Version an. In der System.Windows.Forms.OpenFileDialog-Klasse müssen Sie einen Verweis auf System.Windows.Forms hinzufügen.
quelle
Basierend auf Oyuns Antwort ist es besser, eine Abhängigkeitseigenschaft für den Ordnernamen zu verwenden. Dies ermöglicht (zum Beispiel) das Binden an Untereigenschaften, was im Original nicht funktioniert. In meiner angepassten Version wird im Dialogfeld der ursprüngliche Ordner ausgewählt.
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); } } }
quelle
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Die Ookii-Dialoge für WPF verfügen über eine
VistaFolderBrowserDialog
Klasse, die eine vollständige Implementierung eines Ordner-Browser-Dialogs für WPF bietet.Es gibt auch eine Version, die mit Windows Forms funktioniert .
quelle
Die
FolderBrowserDialog
Klasse vonSystem.Windows.Forms
ist die empfohlene Methode zum Anzeigen eines Dialogfelds, in dem ein Benutzer einen Ordner auswählen kann.Bis vor kurzem stimmte das Erscheinungsbild und Verhalten dieses Dialogfelds nicht mit den anderen Dateisystemdialogen überein. Dies ist einer der Gründe, warum Benutzer es nur ungern verwendeten.
Die gute Nachricht ist, dass
FolderBrowserDialog
es in NET Core 3.0 "modernisiert" wurde und daher eine praktikable Option für diejenigen ist, die entweder Windows Forms oder WPF-Apps schreiben, die auf diese Version oder höher abzielen.Um in einer NET Core WPF-App zu referenzieren
System.Windows.Forms
, muss die Projektdatei bearbeitet und die folgende Zeile hinzugefügt werden:<UseWindowsForms>true</UseWindowsForms>
Dies kann direkt nach dem vorhandenen platziert werden
<UseWPF>
Element platziert werden.Dann müssen Sie nur noch den Dialog verwenden:
using System; using System.Windows.Forms; ... using var dialog = new FolderBrowserDialog { Description = "Time to select a folder", UseDescriptionForTitle = true, SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + Path.DirectorySeparatorChar, ShowNewFolderButton = true }; if (dialog.ShowDialog() == DialogResult.OK) { ... }
FolderBrowserDialog
hat eineRootFolder
Eigenschaft, die angeblich "den Stammordner festlegt, von dem aus das Browsen beginnt", aber was auch immer ich darauf gesetzt habe, hat keinen Unterschied gemacht;SelectedPath
schien die bessere Eigenschaft für diesen Zweck zu sein, jedoch ist der nachfolgende Backslash erforderlich.Außerdem
ShowNewFolderButton
scheint die Eigenschaft ebenfalls ignoriert zu werden. Die Schaltfläche wird unabhängig davon immer angezeigt.quelle
Nur ein solcher Dialog ist FileDialog . Es ist Teil von WinForms, aber es ist eigentlich nur ein Wrapper um den WinAPI-Standard-OS-Dateidialog. Und ich denke nicht, dass es hässlich ist, es ist tatsächlich Teil des Betriebssystems, also sieht es so aus, als würde es ausgeführt.
Auf andere Weise gibt es nichts, bei dem Sie helfen können. Sie müssen entweder nach einer Implementierung durch einen Drittanbieter suchen, entweder kostenlos (und ich glaube nicht, dass es etwas Gutes gibt) oder bezahlt.
quelle
Nur um eins zu sagen,
WindowsAPICodePack
kannCommonOpenFileDialog
unter Windows 7 6.1.7600 nicht geöffnet werden .quelle