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
Does WPF have a native file dialog?
提问by Sebastian Gray
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 reference to System.Windows.Forms
or 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.Win32
namespace (although still part of WPF). See the OpenFileDialog
and SaveFileDialog
classes in particular.
WPF 确实有内置(虽然不是本机)文件对话框。具体来说,它们位于稍微意外的Microsoft.Win32
命名空间中(尽管仍然是 WPF 的一部分)。请特别参阅OpenFileDialog
和SaveFileDialog
类。
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.
但是请注意,正如父命名空间所建议的那样,这些类只是 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;
}
};
};
}
}