Does WPF have a native file dialog?

前端 未结 4 619
迷失自我
迷失自我 2020-12-23 16:09

Under System.Windows.Controls, I can see a PrintDialog However, I can\'t seem to find a native FileDialog. Do I need to create a refe

相关标签:
4条回答
  • 2020-12-23 16:46

    Thanks to Gregor S for a neat solution.

    In Visual Studio 2010 it seems to crash the designer however - so I've tweaked the code in the OpenFileDialogEx class. The XAML code stays the same:

    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;
                    }
                };
            };
        }
    }
    
    0 讨论(0)
  • 2020-12-23 16:50

    I used the solution presented by Gregor S. and it works well, although I had to convert it to a VB.NET solution, here is my conversion if it helps anyone...

    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
    
    0 讨论(0)
  • 2020-12-23 16:57

    WPF does have built-in (although not native) file dialogs. Specifically, they are in the slightly unexpected Microsoft.Win32 namespace (although still part of WPF). See the OpenFileDialog and SaveFileDialog classes in particular.

    Do however note that these classes are only wrappers around the Win32 functionality, as the parent namespace suggests. It does however mean that you don't need to do any WinForms or Win32 interop, which makes it somewhat nicer to use. Unfortunately, the dialogs are by default style in the "old" Windows theme, and you need a small hack in app.manifest to force it to use the new one.

    0 讨论(0)
  • 2020-12-23 17:04

    You can create a simple attached property to add this functionality to a TextBox. Open file dialog can be used like this:

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

    The code for 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;
              }
    
            };
          };
        }
    }
    
    0 讨论(0)
提交回复
热议问题