2009-09-27 6 views

Répondre

60

WPF possède des boîtes de dialogue de fichier intégrées (bien que non natif). Plus précisément, ils sont dans l'espace de noms légèrement inattendu Microsoft.Win32 (bien que toujours partie de WPF). Voir les classes OpenFileDialog et SaveFileDialog en particulier. Notez cependant que ces classes ne sont que des wrappers autour de la fonctionnalité Win32, comme le suggère l'espace de noms parent. Cela signifie cependant que vous n'avez pas besoin de faire de WinForms ou Win32 interop, ce qui le rend un peu plus agréable à utiliser. Malheureusement, les dialogues sont de style par défaut dans le "vieux" thème Windows, et vous avez besoin d'un petit hack dans app.manifest pour le forcer à utiliser le nouveau.

+3

Pourriez-vous élaborer sur ce qui doit être fait avec le manifeste afin d'obtenir la nouvelle version du thème Windows? –

+2

@Sebastian: Bien sûr - il est détaillé sur ce blog: http://www.nbdtech.com/blog/archive/2008/06/16/The-Application-Manifest-Needed-for-XP-and-Vista-Style -File.aspx. – Noldorin

15

Vous pouvez créer une propriété jointe simple pour ajouter cette fonctionnalité à un TextBox. dialogue Ouvrir le fichier peut être utilisé comme celui-ci:

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

Le code pour 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

J'ai utilisé la solution présentée par Gregor S. et il fonctionne bien, même si je devais convertissez-le en une solution VB.NET, voici ma conversion si elle aide n'importe qui ...

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

Grâce à Gregor S pour une solution soignée.

Dans Visual Studio 2010, le concepteur semble toutefois planter - j'ai donc modifié le code dans la classe OpenFileDialogEx. Le code XAML reste le même:

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