2008-08-14 19 views

Respuesta

0

Puede usar un TreeView en combinación con la clase DirectoryInfo.

5

Puede utilizar la clase FolderBrowserDialog desde el espacio de nombres System.Windows.Forms.

+0

-1 Duplo http://stackoverflow.com/a/11775/11635 –

1

No intente hacer rodar el suyo con una clase TreeView/DirectoryInfo. Por un lado, hay muchas características bonitas que obtienes gratis (iconos/clic derecho/redes) usando SHBrowseForFolder. Por otro lado, hay un margen de casos/capturas de los que probablemente no se dé cuenta.

0

Para mucha más funcionalidad que el FolderBrowserdialog, como el filtrado, casillas de verificación, etc., eche un vistazo a controles de terceros como Shell MegaPack. Dado que son controles, pueden colocarse en sus propias formas en lugar de aparecer como un cuadro de diálogo modal.

+0

buena idea si se requiere una selección, etc. –

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

No te olvides de envolver en el uso de usando (carpeta FolderBrowserDialogBrowserDialog1 = new FolderBrowserDialog()) –

7

Nota: no hay garantía de este código funcionará en futuras versiones de .NET Framework. El uso de elementos internos privados de .Net como se hace aquí a través de la reflexión probablemente no sea bueno en general. Use la solución de interoperabilidad mencionada en la parte inferior, ya que es menos probable que la API de Windows cambie.

Si usted está buscando un selector de carpetas que se parece más al de diálogo de Windows 7, con la posibilidad de copiar y pegar de un cuadro de texto en la parte inferior y el panel de navegación de la izquierda con los favoritos y los lugares comunes, entonces puedes tener acceso a eso de una manera muy ligera.

El FolderBrowserDialog interfaz de usuario es muy mínimo:

enter image description here

Pero usted puede tener esto en su lugar:

enter image description here

Aquí es una clase que se abre un selector de carpeta de estilo Vista utilizando el. Interfaz privada neta IFileDialog, sin utilizar directamente interoperabilidad en el código (.Net se encarga de eso). Se vuelve al cuadro de diálogo anterior a Vista si no se encuentra en una versión suficientemente alta de Windows. Debería funcionar en Windows 7, 8, 9, 10 y superior (teóricamente).

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

que desarrollaron esto como una versión limpia de .NET Win 7-style folder select dialog por Bill Seddon de lyquidity.com (no tengo ninguna afiliación). Escribí el mío porque su solución requiere una clase Reflection adicional que no es necesaria para este propósito específico, usa control de flujo basado en excepciones, no almacena en caché los resultados de sus llamadas de reflexión. Tenga en cuenta que la clase estática anidada VistaDialog es para que sus variables de reflexión estática no intenten rellenarse si nunca se llama al método Show.

Se utiliza como tal en un formulario Windows:

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

Por supuesto, puede jugar con sus opciones y qué propiedades se expone. Por ejemplo, permite multiselección en el cuadro de diálogo Vista-style.

Además, tenga en cuenta que Simon Mourier gave an answer muestra cómo hacer exactamente el mismo trabajo utilizando la interoperación directamente con la API de Windows, aunque su versión tendría que completarse para usar el diálogo de estilo anterior si en una versión anterior de Windows. Lamentablemente, todavía no había encontrado su publicación cuando trabajé en mi solución. ¡Nombra tu veneno!

Cuestiones relacionadas