c# - net - select directory windows forms
Seleccionar el diálogo de carpeta WPF (8)
Desarrollo una aplicación WPF4 y en mi aplicación necesito que el usuario seleccione una carpeta donde la aplicación almacenará algo (archivos, informes generados, etc.).
Mis requisitos:
Posibilidad de ver el árbol de carpetas estándar
Posibilidad de seleccionar una carpeta
WPF look & feel, este diálogo debe verse como parte de una aplicación moderna diseñada para Windows Vista / 7 y no para Windows 2000 o incluso Win9x.
Según entiendo, hasta 2010 (.Net 4.0) no habrá un diálogo de carpeta estándar, pero tal vez haya algunos cambios en la versión 4.0.
¿O todo lo que hay que hacer es usar el cuadro de diálogo WinForms de la vieja escuela? Si es la única forma de hacer lo que necesito, ¿cómo puedo acercarme más al estilo Vista / 7 y no a Win9x?
En algunos foros, vi la implementación de dichos diálogos, pero con viejos iconos feos como Windows 95. Realmente no se ve bien.
Agregue el Código API de Windows Pack-Shell a su proyecto
using Microsoft.WindowsAPICodePack.Dialogs;
...
var dialog = new CommonOpenFileDialog();
dialog.IsFolderPicker = true;
CommonFileDialogResult result = dialog.ShowDialog();
Escribí sobre esto en mi blog hace mucho tiempo, el soporte de WPF para los diálogos de archivos comunes es realmente malo (o al menos estaba en 3.5 no revisé en la versión 4), pero es fácil evitarlo.
Debe agregar el manifiesto correcto a su aplicación, que le dará un estilo moderno de cuadros de mensajes y carpetas (WinForms FolderBrowserDialog) pero no WPF abrir / guardar diálogos, esto se describe en esas 3 publicaciones (si no le importa) acerca de la explicación y solo quiere que la solución vaya directamente al tercero):
- ¿Por qué recibo cuadros de diálogo y cuadros de diálogo de estilo antiguo con WPF?
- ¿Configurará un manifiesto para resolver mis problemas de estilo del cuadro de mensaje de WPF?
- El manifiesto de la aplicación necesaria para cuadros de diálogo y cuadros de diálogo de estilo de XP y Vista con WPF
Afortunadamente, los diálogos de abrir / guardar son envoltorios muy delgados alrededor de la API de Win32 que es fácil de llamar con los indicadores adecuados para obtener el estilo Vista / 7 (después de configurar el manifiesto)
MVVM + WinForms FolderBrowserDialog como comportamiento
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);
}
}
}
Uso
<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
Microsoft.Win32.OpenFileDialog es el cuadro de diálogo estándar que utiliza cualquier aplicación en Windows. Su usuario no se sorprenderá por su apariencia cuando use WPF en .NET 4.0
El diálogo fue alterado en Vista. WPF en .NET 3.0 y 3.5 todavía usaba el diálogo heredado, pero eso fue corregido en .NET 4.0. Solo puedo adivinar que comenzaste este hilo porque estás viendo ese viejo diálogo. Lo que probablemente significa que en realidad está ejecutando un programa que se dirige a 3.5. Sí, el contenedor de Winforms recibió la actualización y muestra la versión de Vista. Clase System.Windows.Forms.OpenFileDialog, deberá agregar una referencia a System.Windows.Forms.
Según la respuesta de Oyun, es mejor usar una propiedad de dependencia para FolderName. Esto permite (por ejemplo) enlazar a sub-propiedades, lo que no funciona en el original. Además, en mi versión ajustada, el cuadro de diálogo muestra la selección de la carpeta inicial.
Uso en XAML:
<Button Content="...">
<i:Interaction.Behaviors>
<Behavior:FolderDialogBehavior FolderName="{Binding FolderPathPropertyName, Mode=TwoWay}"/>
</i:Interaction.Behaviors>
</Button>
Código:
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);
}
}
}
Si no quiere usar Windows Forms ni editar archivos manifiestos, se me ocurrió un truco muy simple usando el diálogo SaveAs de WPF para realmente seleccionar un directorio.
No se necesita una directiva de uso, ¡simplemente copie y pegue el código a continuación!
Debería ser muy fácil de usar y la mayoría de las personas nunca lo notarán.
La idea surge del hecho de que podemos cambiar el título de ese diálogo, ocultar archivos y trabajar con el nombre del archivo resultante con bastante facilidad.
Es un gran truco seguro, pero tal vez hará el trabajo bien para su uso ...
En este ejemplo, tengo un objeto de cuadro de texto para contener la ruta resultante, pero puede eliminar las líneas relacionadas y usar un valor de retorno si lo desea ...
// 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;
}
Los únicos problemas con este truco son:
- El botón Confirmar aún dice "Guardar" en lugar de algo como "Seleccionar directorio", pero en un caso como minas "Guardo" la selección del directorio para que funcione ...
- El campo de entrada todavía dice "Nombre de archivo" en lugar de "Nombre de directorio", pero podemos decir que un directorio es un tipo de archivo ...
- Todavía hay un menú desplegable "Guardar como tipo", pero su valor dice "Directorio (* .this.directory)", y el usuario no puede cambiarlo por otra cosa, funciona para mí ...
La mayoría de las personas no se darán cuenta de esto, aunque definitivamente preferiría usar una forma oficial de WPF si Microsoft les saca la cabeza fuera de sí, pero hasta que lo hagan, esa es mi solución temporal.
Solo ese diálogo es FileDialog . Es parte de WinForms, pero en realidad es la única envoltura del diálogo de archivo del sistema operativo estándar WinAPI. Y no creo que sea feo, en realidad es parte del sistema operativo, por lo que parece que se ejecuta el sistema operativo.
De otra manera, no hay nada para ayudarte. O necesita buscar la implementación de terceros, ya sea gratis (y no creo que haya ningún bien) o pagado.
El libro de cocina de Windows Presentation Foundation 4.5 de Pavel Yosifovich en la página 155 en la sección "Uso de los cuadros de diálogo comunes" dice:
"¿Qué pasa con la selección de carpetas (en lugar de archivos)? WPF OpenFileDialog no es compatible con eso. Una solución es utilizar la clase FolderBrowseDialog de Windows Forms. Otra buena solución es utilizar el paquete de códigos API de Windows descrito en breve".
Descargué el API Code Pack del paquete de código API de Windows® para Microsoft® .NET Framework Paquete de código API de Windows: ¿Dónde está? , luego agregué referencias a Microsoft.WindowsAPICodePack.dll y Microsoft.WindowsAPICodePack.Shell.dll a mi proyecto de WPF 4.5.
Ejemplo:
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
}