2008-08-14 10 views

Antwort

0

Sie könnten eine TreeView in Kombination mit der DirectoryInfo-Klasse verwenden.

5

Sie könnten einfach die FolderBrowserDialog Klasse aus dem Namespace System.Windows.Forms verwenden.

+0

-1 Dup http://StackOverflow.com/a/11775/11635 –

1

Bitte versuchen Sie nicht, eigene mit einer TreeView/DirectoryInfo-Klasse zu rollen. Zum einen gibt es viele nette Funktionen, die Sie kostenlos erhalten (Icons/Rechtsklick/Netzwerke), indem Sie SHBrowseForFolder verwenden. Zum anderen gibt es einen Rand Fällen/Fänge Sie werden wahrscheinlich nicht bewusst sein.

0

Für viel mehr Funktionalität als das FolderBrowserdialog, wie Filterung, Check-Boxen, etc, schauen Sie sich 3rd-Party-Kontrollen wie Shell MegaPack. Da es sich um Steuerelemente handelt, können sie in Ihre eigenen Formen eingefügt werden, anstatt als modaler Dialog zu erscheinen.

+0

gute Idee, wenn Auswahl usw. erforderlich ist. –

71
string folderPath = ""; 
FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog(); 
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) { 
    folderPath = folderBrowserDialog1.SelectedPath ; 
} 
+3

Vergessen Sie nicht, in eine Verwendung von mit (FolderBrowserDialog ordnerBrowserDialog1 = neuer FolderBrowserDialog()) –

7

Hinweis: Es gibt keine Garantie, diesen Code in zukünftigen Versionen des .NET Framework arbeiten. Die Verwendung privater .Net-Framework-Interna, wie hier durch Reflektion getan, ist wahrscheinlich insgesamt nicht gut. Verwenden Sie die unten genannte Interop-Lösung, da sich die Windows-API weniger wahrscheinlich ändert.

Wenn Sie einen Ordner Picker suchen, der mehr wie die Windows 7 Dialog sieht, mit der Fähigkeit, aus einer Textbox an der Unterseite und dem Navigationsbereich auf der linken Seite mit den Favoriten und gemeinsame Positionen zu kopieren und einzufügen, dann können Sie leicht darauf zugreifen.

Der Folder UI ist sehr gering:

enter image description here

Aber Sie können dies stattdessen haben:

enter image description here

Hier sind eine Klasse, die einen Vista-Stil-Ordner Wähler das öffnet. Net private IFileDialog Schnittstelle, ohne direkt Interop in den Code (. Net kümmert sich darum für Sie). Es fällt zurück auf den Pre-Vista-Dialog, wenn nicht in einer ausreichend hohen Windows-Version. Sollte unter Windows 7, 8, 9, 10 und höher (theoretisch) funktionieren.

using System; 
using System.Reflection; 
using System.Windows.Forms; 

namespace MyCoolCompany.Shuriken { 
    /// <summary> 
    /// Present the Windows Vista-style open file dialog to select a folder. Fall back for older Windows Versions 
    /// </summary> 
    public class FolderSelectDialog { 
     private string _initialDirectory; 
     private string _title; 
     private string _fileName = ""; 

     public string InitialDirectory { 
      get { return string.IsNullOrEmpty(_initialDirectory) ? Environment.CurrentDirectory : _initialDirectory; } 
      set { _initialDirectory = value; } 
     } 
     public string Title { 
      get { return _title ?? "Select a folder"; } 
      set { _title = value; } 
     } 
     public string FileName { get { return _fileName; } } 

     public bool Show() { return Show(IntPtr.Zero); } 

     /// <param name="hWndOwner">Handle of the control or window to be the parent of the file dialog</param> 
     /// <returns>true if the user clicks OK</returns> 
     public bool Show(IntPtr hWndOwner) { 
      var result = Environment.OSVersion.Version.Major >= 6 
       ? VistaDialog.Show(hWndOwner, InitialDirectory, Title) 
       : ShowXpDialog(hWndOwner, InitialDirectory, Title); 
      _fileName = result.FileName; 
      return result.Result; 
     } 

     private struct ShowDialogResult { 
      public bool Result { get; set; } 
      public string FileName { get; set; } 
     } 

     private static ShowDialogResult ShowXpDialog(IntPtr ownerHandle, string initialDirectory, string title) { 
      var folderBrowserDialog = new FolderBrowserDialog { 
       Description = title, 
       SelectedPath = initialDirectory, 
       ShowNewFolderButton = false 
      }; 
      var dialogResult = new ShowDialogResult(); 
      if (folderBrowserDialog.ShowDialog(new WindowWrapper(ownerHandle)) == DialogResult.OK) { 
       dialogResult.Result = true; 
       dialogResult.FileName = folderBrowserDialog.SelectedPath; 
      } 
      return dialogResult; 
     } 

     private static class VistaDialog { 
      private const string c_foldersFilter = "Folders|\n"; 

      private const BindingFlags c_flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 
      private readonly static Assembly s_windowsFormsAssembly = typeof(FileDialog).Assembly; 
      private readonly static Type s_iFileDialogType = s_windowsFormsAssembly.GetType("System.Windows.Forms.FileDialogNative+IFileDialog"); 
      private readonly static MethodInfo s_createVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("CreateVistaDialog", c_flags); 
      private readonly static MethodInfo s_onBeforeVistaDialogMethodInfo = typeof(OpenFileDialog).GetMethod("OnBeforeVistaDialog", c_flags); 
      private readonly static MethodInfo s_getOptionsMethodInfo = typeof(FileDialog).GetMethod("GetOptions", c_flags); 
      private readonly static MethodInfo s_setOptionsMethodInfo = s_iFileDialogType.GetMethod("SetOptions", c_flags); 
      private readonly static uint s_fosPickFoldersBitFlag = (uint) s_windowsFormsAssembly 
       .GetType("System.Windows.Forms.FileDialogNative+FOS") 
       .GetField("FOS_PICKFOLDERS") 
       .GetValue(null); 
      private readonly static ConstructorInfo s_vistaDialogEventsConstructorInfo = s_windowsFormsAssembly 
       .GetType("System.Windows.Forms.FileDialog+VistaDialogEvents") 
       .GetConstructor(c_flags, null, new[] { typeof(FileDialog) }, null); 
      private readonly static MethodInfo s_adviseMethodInfo = s_iFileDialogType.GetMethod("Advise"); 
      private readonly static MethodInfo s_unAdviseMethodInfo = s_iFileDialogType.GetMethod("Unadvise"); 
      private readonly static MethodInfo s_showMethodInfo = s_iFileDialogType.GetMethod("Show"); 

      public static ShowDialogResult Show(IntPtr ownerHandle, string initialDirectory, string title) { 
       var openFileDialog = new OpenFileDialog { 
        AddExtension = false, 
        CheckFileExists = false, 
        DereferenceLinks = true, 
        Filter = c_foldersFilter, 
        InitialDirectory = initialDirectory, 
        Multiselect = false, 
        Title = title 
       }; 

       var iFileDialog = s_createVistaDialogMethodInfo.Invoke(openFileDialog, new object[] { }); 
       s_onBeforeVistaDialogMethodInfo.Invoke(openFileDialog, new[] { iFileDialog }); 
       s_setOptionsMethodInfo.Invoke(iFileDialog, new object[] { (uint) s_getOptionsMethodInfo.Invoke(openFileDialog, new object[] { }) | s_fosPickFoldersBitFlag }); 
       var adviseParametersWithOutputConnectionToken = new[] { s_vistaDialogEventsConstructorInfo.Invoke(new object[] { openFileDialog }), 0U }; 
       s_adviseMethodInfo.Invoke(iFileDialog, adviseParametersWithOutputConnectionToken); 

       try { 
        int retVal = (int) s_showMethodInfo.Invoke(iFileDialog, new object[] { ownerHandle }); 
        return new ShowDialogResult { 
         Result = retVal == 0, 
         FileName = openFileDialog.FileName 
        }; 
       } 
       finally { 
        s_unAdviseMethodInfo.Invoke(iFileDialog, new[] { adviseParametersWithOutputConnectionToken[1] }); 
       } 
      } 
     } 

     // Wrap an IWin32Window around an IntPtr 
     private class WindowWrapper : IWin32Window { 
      private readonly IntPtr _handle; 
      public WindowWrapper(IntPtr handle) { _handle = handle; } 
      public IntPtr Handle { get { return _handle; } } 
     } 
    } 
} 

entwickelte ich dies als aufgeräumt Version von .NET Win 7-style folder select dialog von Bill Seddon von lyquidity.com (ich habe keine Verbindung). Ich habe meine eigene geschrieben, weil seine Lösung eine zusätzliche Reflection-Klasse benötigt, die für diesen fokussierten Zweck nicht benötigt wird, eine ausnahmebasierte Flusssteuerung verwendet, die Ergebnisse ihrer Reflektionsaufrufe nicht zwischenspeichert. Beachten Sie, dass die geschachtelte statische Klasse VistaDialog so ist, dass ihre statischen Reflexionsvariablen nicht versucht werden, Daten zu liefern, wenn die Methode Show nie aufgerufen wird.

Es ist wie so in einem Windows Form verwendet:

var dialog = new FolderSelectDialog { 
    InitialDirectory = musicFolderTextBox.Text, 
    Title = "Select a folder to import music from" 
}; 
if (dialog.Show(Handle)) { 
    musicFolderTextBox.Text = dialog.FileName; 
} 

Sie natürlich mit seinen Optionen und es macht, welche Eigenschaften rumspielen kann. Zum Beispiel erlaubt es Mehrfachauswahl im Vista-Stil Dialog.

Bitte beachten Sie auch, dass Simon Mourier gave an answer zeigt, wie Sie den gleichen Job mit Interop direkt gegenüber der Windows-API tun, obwohl seine Version ergänzt werden müsste, um den älteren Stil Dialog verwenden, wenn in einer älteren Version von Windows. Leider hatte ich seinen Beitrag noch nicht gefunden, als ich meine Lösung aufgearbeitet habe. Nenne dein Gift!

Verwandte Themen