Control para seleccionar Carpetas [Solucionado]

Iniciado por Maurice_Lupin, 22 Febrero 2014, 23:53 PM

0 Miembros y 1 Visitante están viendo este tema.

Maurice_Lupin

Hola, estoy buscando un control que me permita seleccionar carpetas, no quiero utilizar el FolderBrowserDialog pues es un lio explorar.

Se puede utilizar el control OpenFileDialog para seleccionar carpetas?. Si alguien tiene un link, info... que pueda compartir, quizá algun control personalizado.

Lo último que se me ocurre es usar el SaveFileDialog.

Saludos.




;D buscando en ingles, encontré lo que buscaba.




link: http://www.codeproject.com/Articles/44914/Select-file-or-folder-from-the-same-dialog

comparto el code, quizá a alguien le interese.

Código (vbnet) [Seleccionar]

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
using System.Windows.Forms;

public class FileFolderDialog : CommonDialog
{
private OpenFileDialog dialog = new OpenFileDialog();

public OpenFileDialog Dialog
{
get { return dialog; }
set { dialog = value; }
}

public new DialogResult ShowDialog()
{
return this.ShowDialog(null);
}

public new DialogResult ShowDialog(IWin32Window owner)
{
// Set validate names to false otherwise windows will not let you select "Folder Selection."
dialog.ValidateNames = false;
dialog.CheckFileExists = false;
dialog.CheckPathExists = true;

try
{
// Set initial directory (used when dialog.FileName is set from outside)
if (dialog.FileName != null && dialog.FileName != "")
{
if (Directory.Exists(dialog.FileName))
dialog.InitialDirectory = dialog.FileName;
else
dialog.InitialDirectory = Path.GetDirectoryName(dialog.FileName);
}
}
catch (Exception ex)
{
// Do nothing
}

// Always default to Folder Selection.
dialog.FileName = "Folder Selection.";

if (owner == null)
return dialog.ShowDialog();
else
return dialog.ShowDialog(owner);
}

/// <summary>
// Helper property. Parses FilePath into either folder path (if Folder Selection. is set)
// or returns file path
/// </summary>
public string SelectedPath
{
get {
try
{
if (dialog.FileName != null &&
(dialog.FileName.EndsWith("Folder Selection.") || !File.Exists(dialog.FileName)) &&
!Directory.Exists(dialog.FileName))
{
return Path.GetDirectoryName(dialog.FileName);
}
else
{
return dialog.FileName;
}
}
catch (Exception ex)
{
return dialog.FileName;
}
}
set
{
if (value != null && value != "")
{
dialog.FileName = value;
}
}
}

/// <summary>
/// When multiple files are selected returns them as semi-colon seprated string
/// </summary>
public string SelectedPaths
{
get {
if (dialog.FileNames != null && dialog.FileNames.Length > 1)
{
StringBuilder sb = new StringBuilder();
foreach (string fileName in dialog.FileNames)
{
try
{
if (File.Exists(fileName))
sb.Append(fileName + ";");
}
catch (Exception ex)
{
// Go to next
}
}
return sb.ToString();
}
else
{
return null;
}
}
}

public override void Reset()
{
dialog.Reset();
}

protected override bool RunDialog(IntPtr hwndOwner)
{
return true;
}
}


uso:
Código (vbnet) [Seleccionar]

FileFolderDialog ffD = new FileFolderDialog();
ffD.ShowDialog(this);


Saludos.
Un error se comete al equivocarse.

Eleкtro

#1
(Porfavor la próxima vez no hagas doble post, utiliza el botón MODIFICAR)




Tienes toda la razón del mundo, es un coñazo usar el FolderBrowserDialog, yo lo veo como un diálogo obsoleto y dificil de manejar, con muy poco rendimiento, ya que con el diálogo de carpetas de Windows puedes acceder a una ubicación en 5 segundos escribiendo la ubicación o usando las ubicaciones favoritas, mientras que con el FolderBrowserDialog pierdes mucho más tiempo expandiendo carpetas ...una por una.
Es una completa basura.

La solución de terceros que has mostrado ....bueno, es una solución y es customizable, pero no tiene ventajas sobre la navegación de directorios, debería customizarse en más aspectos la Class ...cosa que resultaría laboriosa. Así que sin ánimo de ofender al autor del código, me parece algo muy cutre heredar un 'CommonDialog' para hacer sólamente eso.

Te propongo algo más eficiente, usando la librería Windows API Code Pack que provee Microsoft.

Te muestro un ejemplo de uso:

Código (vbnet) [Seleccionar]
   ' WindowsAPICodePack 'CommonOpenFileDialog' Example.
   ' ( By Elektro )
   '
   ' Instructions:
   ' 1. Reference "Microsoft.WindowsAPICodePack.dll" and "Microsoft.WindowsAPICodePack.Shell.dll".

   Imports Microsoft.WindowsAPICodePack.Dialogs
   Imports Microsoft.WindowsAPICodePack.Shell

   ''' <summary>
   ''' The WindowsAPICodePack 'CommonOpenFileDialog' instance.
   ''' </summary>
   Private WithEvents FolderPicker As New CommonOpenFileDialog With
       {
           .Title = "Folder Picker Test",
           .DefaultDirectory = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
           .InitialDirectory = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
           .DefaultFileName = "C:\",
           .IsFolderPicker = True,
           .Multiselect = False,
           .ShowPlacesList = True,
           .ShowHiddenItems = True,
           .EnsurePathExists = True,
           .RestoreDirectory = False,
           .NavigateToShortcut = True,
           .AllowNonFileSystemItems = True,
           .AddToMostRecentlyUsedList = True
       }

   ''' <summary>
   ''' Handles the Click event of the Button1 control.
   ''' </summary>
   ''' <param name="sender">The source of the event.</param>
   ''' <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
   Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

       ' If folder is picked then...
       If FolderPicker.ShowDialog() = CommonFileDialogResult.Ok Then

           Dim SelectedFolder As ShellObject = FolderPicker.FileAsShellObject
           MsgBox(SelectedFolder.GetDisplayName(DisplayNameType.FileSystemPath))

       End If

       ' FolderPicker.Dispose()

   End Sub

   ''' <summary>
   ''' Handles the FolderChanging event of the FolderPicker control.
   ''' </summary>
   ''' <param name="sender">The source of the event.</param>
   ''' <param name="e">The <see cref="Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialogFolderChangeEventArgs"/> instance containing the event data.</param>
   Private Sub FolderPicker_FolderChanging(sender As Object, e As CommonFileDialogFolderChangeEventArgs) _
   Handles FolderPicker.FolderChanging

       ' Restrict the navigation on specific folders.
       Select Case True

           Case e.Folder = Environment.GetFolderPath(Environment.SpecialFolder.Windows)
               '  Restricts the navigation to 'Windows' directory.
               e.Cancel = True

           Case e.Folder.Equals("C:\Juegos", StringComparison.CurrentCultureIgnoreCase)
               ' Restricts the navigation to 'C:\Juegos' directory.
               e.Cancel = True

           Case e.Folder.Split("\").Last.Equals("Administrador", StringComparison.CurrentCultureIgnoreCase)
               ' Restricts the navigation to any directory name ending in "Administrador" keyword.
               e.Cancel = True

           Case Else
               ' Allow navigation on that directory.
               e.Cancel = False

       End Select

   End Sub


PD: Y si no quieres depender de librerías siempre puedes sacar la parte importante del código fuente que va incluido.
PD: Además, ese kit de librerías en el futuro te proporcionarían ventajas y comodidades para usar otros tipos de controles y classes muy interesantes.

O también puedes usar la librería Ooki Dialogs, que son diálogos basados en Windows VISTA y es la librería que yo usaba como reemplazamiento del 'FolderBrowserDialog', antes de conocer la existencia de 'WindowsAPICodePack'.

Un mini ejemplo de uso:

Código (vbnet) [Seleccionar]
 Dim FolderPicker As New Ookii.Dialogs.VistaFolderBrowserDialog
 FolderPicker.ShowNewFolderButton = True

 If FolderPicker.ShowDialog.ToString() = "OK" Then
     msgbox(FolderPicker.SelectedPath)
 End If

 ' FolderPicker.Dispose()


Saludos.








Maurice_Lupin

#2
Hola, Elektro.
No me había dado cuenta que hice doble post, lo siento. Interesante la libreria que comentas, me la bajé completa, estoy dandole una ojeada.

Me has hecho recordar que se puede usar la API también. Encontré esta info:

http://vbnet.mvps.org/index.html?code/hooks/fileopensavedlghookadvtext.htm

Está en vb6 pero usando http://www.pinvoke.net se puede implementar en vb.net, si puedo estos dias lo adapto.




Me parece laborioso pero, ummm las posibilidades son buenisimas.

Saludos y gracias por responder.
Un error se comete al equivocarse.