WPF有一个本地文件对话框?
在System.Windows.Controls
,我可以看到一个PrintDialog
但是,我似乎无法find一个本地的FileDialog
。 我是否需要创build一个对System.Windows.Forms
的引用还是有另一种方法?
WPF确实有内置的(虽然不是本地的 )文件对话框。 具体来说,他们在稍微意外的Microsoft.Win32
命名空间(尽pipe仍然是WPF的一部分)。 尤其请参阅OpenFileDialog
和SaveFileDialog
类。
但请注意,这些类只是包装Win32的function,因为父命名空间build议。 但是这意味着你不需要做任何WinForms或Win32互操作,这使得它更好用。 不幸的是,这个对话框在“旧”Windows主题中是默认的样式,而你需要在app.manifest
进行一些小的操作来强制它使用新的。
您可以创build一个简单的附加属性来将此function添加到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>
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; } }; }; } }
我使用Gregor S.提出的解决scheme,它运行良好,但我不得不将其转换为VB.NET解决scheme,这是我的转换,如果它可以帮助任何人…
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
感谢Gregor S一个整洁的解决scheme。
在Visual Studio 2010中它似乎让devise者崩溃 – 所以我调整了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; } }; }; } }