C# WPF 是否有本机文件对话框?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1482486/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 17:57:39  来源:igfitidea点击:

Does WPF have a native file dialog?

c#wpffiledialog

提问by Sebastian Gray

Under System.Windows.Controls, I can see a PrintDialogHowever, I can't seem to find a native FileDialog. Do I need to create a reference to System.Windows.Formsor is there another way?

在 下System.Windows.Controls,我可以看到 aPrintDialog但是,我似乎找不到本地FileDialog. 我需要创建一个引用System.Windows.Forms还是有其他方法?

采纳答案by Noldorin

WPF does have built-in (although not native) file dialogs. Specifically, they are in the slightly unexpected Microsoft.Win32namespace (although still part of WPF). See the OpenFileDialogand SaveFileDialogclasses in particular.

WPF 确实有内置(虽然不是本机)文件对话框。具体来说,它们位于稍微意外的Microsoft.Win32命名空间中(尽管仍然是 WPF 的一部分)。请特别参阅OpenFileDialogSaveFileDialog类。

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.manifestto force it to use the new one.

但是请注意,正如父命名空间所建议的那样,这些类只是 Win32 功能的包装器。然而,这确实意味着您不需要执行任何 WinForms 或 Win32 互操作,这使得它更好用。不幸的是,对话框在默认情况下是“旧”Windows 主题的样式,您需要稍作修改app.manifest才能强制它使用新主题。

回答by Gregor Slavec

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

您可以创建一个简单的附加属性来将此功能添加到 TextBox。打开文件对话框可以这样使用

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

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

        };
      };
    }
}

回答by Jbtatro

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

我使用了 Gregor S. 提供的解决方案,效果很好,虽然我不得不将它转换为 VB.NET 解决方案,如果它对任何人有帮助,这里是我的转换......

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

回答by Daniel Scott

Thanks to Gregor S for a neat solution.

感谢 Gregor S 提供了一个巧妙的解决方案。

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:

然而,在 Visual Studio 2010 中,它似乎使设计器崩溃 - 所以我调整了 OpenFileDialogEx 类中的代码。XAML 代码保持不变:

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