2009-09-27 19 views

Respuesta

60

WPF tiene diálogos de archivo incorporados (aunque no nativos). Específicamente, están en el espacio de nombre ligeramente inesperado Microsoft.Win32 (aunque todavía forma parte de WPF). Consulte las clases OpenFileDialog y SaveFileDialog en particular.

Sin embargo, tenga en cuenta que estas clases son solo envoltorios de la funcionalidad de Win32, como sugiere el espacio de nombres primario. Sin embargo, significa que no necesita hacer ninguna interoperabilidad WinForms o Win32, lo que hace que sea algo más agradable de usar. Desafortunadamente, los cuadros de diálogo son por estilo predeterminado en el tema "antiguo" de Windows, y necesita un pequeño truco en app.manifest para forzarlo a usar el nuevo.

+3

¿Le importaría elaborar lo que debe hacerse con el manifiesto para obtener la nueva versión del tema de Windows? –

+2

@Sebastian: Claro - se detalla en esta publicación del blog: http://www.nbdtech.com/blog/archive/2008/06/16/The-Application-Manifest-Needed-for-XP-and-Vista-Style -File.aspx. – Noldorin

15

Puede crear una propiedad adjunta simple para agregar esta funcionalidad a un TextBox. de diálogo Abrir el archivo puede ser utilizado como esto:

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*"/> 
     <ColumnDefinition Width="Auto"/> 
    </Grid.ColumnDefinitions> 
    <TextBox i:OpenFileDialogEx.Filter="Excel documents (.xls)|*.xls" Grid.Column="0" /> 
    <Button Grid.Column="1">Browse</Button> 
</Grid> 

El código para OpenFileDialogEx:

public class OpenFileDialogEx 
{ 
    public static readonly DependencyProperty FilterProperty = 
     DependencyProperty.RegisterAttached("Filter", 
     typeof (string), 
     typeof (OpenFileDialogEx), 
     new PropertyMetadata("All documents (.*)|*.*", (d, e) => AttachFileDialog((TextBox) d, e))); 

    public static string GetFilter(UIElement element) 
    { 
     return (string)element.GetValue(FilterProperty); 
    } 

    public static void SetFilter(UIElement element, string value) 
    { 
     element.SetValue(FilterProperty, value); 
    } 

    private static void AttachFileDialog(TextBox textBox, DependencyPropertyChangedEventArgs args) 
    {     
     var parent = (Panel) textBox.Parent; 

     parent.Loaded += delegate { 

     var button = (Button) parent.Children.Cast<object>().FirstOrDefault(x => x is Button); 

     var filter = (string) args.NewValue; 

     button.Click += (s, e) => { 
      var dlg = new OpenFileDialog(); 
      dlg.Filter = filter; 

      var result = dlg.ShowDialog(); 

      if (result == true) 
      { 
      textBox.Text = dlg.FileName; 
      } 

     }; 
     }; 
    } 
} 
3

he utilizado la solución presentada por Gregor S. y funciona bien, aunque tuve que convertirlo en una solución VB.NET, aquí está mi conversión si ayuda a alguien ...

Imports System 
Imports Microsoft.Win32 

Public Class OpenFileDialogEx 
    Public Shared ReadOnly FilterProperty As DependencyProperty = DependencyProperty.RegisterAttached("Filter", GetType(String), GetType(OpenFileDialogEx), New PropertyMetadata("All documents (.*)|*.*", Sub(d, e) AttachFileDialog(DirectCast(d, TextBox), e))) 
    Public Shared Function GetFilter(element As UIElement) As String 
     Return DirectCast(element.GetValue(FilterProperty), String) 
    End Function 

    Public Shared Sub SetFilter(element As UIElement, value As String) 
     element.SetValue(FilterProperty, value) 
    End Sub 


    Private Shared Sub AttachFileDialog(textBox As TextBox, args As DependencyPropertyChangedEventArgs) 
     Dim parent = DirectCast(textBox.Parent, Panel) 
     AddHandler parent.Loaded, Sub() 

      Dim button = DirectCast(parent.Children.Cast(Of Object)().FirstOrDefault(Function(x) TypeOf x Is Button), Button) 
      Dim filter = DirectCast(args.NewValue, String) 
      AddHandler button.Click, Sub(s, e) 
       Dim dlg = New OpenFileDialog() 
       dlg.Filter = filter 
       Dim result = dlg.ShowDialog() 
       If result = True Then 
        textBox.Text = dlg.FileName 
       End If 
      End Sub 
     End Sub 
    End Sub 
End Class 
2

Gracias a Gregor S para una solución ordenada.

Parece que en Visual Studio 2010 se cuelga el diseñador, así que modifiqué el código en la clase OpenFileDialogEx. El código XAML permanece igual:

public class OpenFileDialogEx 
{ 
    public static readonly DependencyProperty FilterProperty = 
     DependencyProperty.RegisterAttached(
      "Filter", 
      typeof(string), 
      typeof(OpenFileDialogEx), 
      new PropertyMetadata("All documents (.*)|*.*", (d, e) => AttachFileDialog((TextBox)d, e)) 
     ); 


    public static string GetFilter(UIElement element) 
    { 
     return (string)element.GetValue(FilterProperty); 
    } 

    public static void SetFilter(UIElement element, string value) 
    { 
     element.SetValue(FilterProperty, value); 
    } 

    private static void AttachFileDialog(TextBox textBox, DependencyPropertyChangedEventArgs args) 
    { 
     var textBoxParent = textBox.Parent as Panel; 
     if (textBoxParent == null) 
     { 
      Debug.Print("Failed to attach File Dialog Launching Button Click Handler to Textbox parent panel!"); 
      return; 
     } 


     textBoxParent.Loaded += delegate 
     { 
      var button = textBoxParent.Children.Cast<object>().FirstOrDefault(x => x is Button) as Button; 
      if (button == null) 
       return; 

      var filter = (string)args.NewValue; 

      button.Click += (s, e) => 
      { 
       var dlg = new OpenFileDialog { Filter = filter }; 

       var result = dlg.ShowDialog(); 

       if (result == true) 
       { 
        textBox.Text = dlg.FileName; 
       } 
      }; 
     }; 
    } 
} 
Cuestiones relacionadas