WPF 入门教程OpenFileDialog和SaveFileDialog

Windows 应用程序中打开或保存文件时,您都会看到大致相同的对话框。原因当然是这些对话框是 Windows API 的一部分,因此 Windows 平台上的开发人员也可以访问。

对于 WPF,您将找到用于在Microsoft.Win32命名空间中打开和保存文件的标准对话框。在本文中,我们将重点介绍OpenFileDialog类,它可以非常轻松地显示用于打开一个或多个文件的对话框。

简单的 OpenFileDialog 示例

让我们开始使用没有任何额外选项的 OpenFileDialog,将文件加载到 TextBox 控件:

<Window x:Class="WpfTutorialSamples.Dialogs.OpenFileDialogSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="OpenFileDialogSample" Height="300" Width="300">
    <DockPanel Margin="10">
        <WrapPanel HorizontalAlignment="Center" DockPanel.Dock="Top" Margin="0,0,0,10">
            <Button Name="btnOpenFile" Click="btnOpenFile_Click">Open file</Button>
        </WrapPanel>
        <TextBox Name="txtEditor" />
    </DockPanel>
</Window>


using System;
using System.IO;
using System.Windows;
using Microsoft.Win32;

namespace WpfTutorialSamples.Dialogs
{
	public partial class OpenFileDialogSample : Window
	{
		public OpenFileDialogSample()
		{
			InitializeComponent();
		}

		private void btnOpenFile_Click(object sender, RoutedEventArgs e)
		{
			OpenFileDialog openFileDialog = new OpenFileDialog();
			if(openFileDialog.ShowDialog() == true)
				txtEditor.Text = File.ReadAllText(openFileDialog.FileName);
		}
	}
}

单击“打开文件”按钮后,将实例化并显示 OpenFileDialog。根据您使用的 Windows 版本和选择的主题,它看起来像这样:

ShowDialog() 将返回一个可为空的布尔值,这意味着它可以是 false、true 或 null。如果用户选择一个文件并按“打开”,则结果为 True,在这种情况下,我们尝试将文件加载到 TextBox 控件中。我们通过使用OpenFileDialog的FileName属性获取所选文件的完整路径 。

推荐一款WPF MVVM框架开源项目:Newbeecoder.UI

Demo下载:

筛选

通常,当您希望用户在您的应用程序中打开文件时,您希望将其限制为一种或几种文件类型。例如,Word 主要打开 Word 文件(扩展名为 .doc 或 .docx),记事本主要打开文本文件(扩展名为 .txt)。

您可以为 OpenFileDialog 指定一个过滤器,以向用户指示他们应该在您的应用程序中打开哪些类型的文件,并限制显示的文件以获得更好的概览。这是通过 Filter 属性完成的,我们可以在初始化对话框后立即将其添加到上面的示例中,如下所示:

openFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";

结果如下:

请注意该对话框现在如何具有用于选择文件类型的组合框,并且显示的文件仅限于具有所选文件类型指定的扩展名的文件。

指定过滤器的格式乍一看可能有点奇怪,但它的工作原理是指定所需文件扩展名的人类可读版本,然后是计算机易于解析的版本,用管道 (|) 分隔特点。如果你想要多个文件类型,就像我们在上面的例子中所做的那样,每组信息也用管道字符分隔。

所以总结一下,下面这部分的意思是我们希望文件类型命名为“文本文件(*.txt)”(括号中的扩展名是对用户的礼貌,所以他们知道包含了哪些扩展名),第二部分告诉对话框显示扩展名为 .txt 的文件:

Text files (*.txt)|*.txt

每种文件类型当然可以有多个扩展名。例如,图像文件可以同时指定为 JPEG 和 PNG 文件,如下所示:

openFileDialog.Filter = "Image files (*.png;*.jpeg)|*.png;*.jpeg|All files (*.*)|*.*";

只需在第二部分(计算机的)中用分号分隔每个扩展 - 在第一部分中,您可以按照您想要的方式对其进行格式化,但大多数开发人员似乎对这两个部分使用相同的表示法,如在上面的例子。

设置初始目录

OpenFileDialog 使用的初始目录由 Windows 决定,但通过使用InitialDirectory属性,您可以覆盖它。您通常会将此值设置为用户指定的目录、应用程序目录或仅设置为上次使用的目录。您可以将其设置为字符串格式的路径,如下所示:

openFileDialog.InitialDirectory = @"c:\temp\";

如果要使用 Windows 上的特殊文件夹之一,例如桌面、我的文档或 Program Files 目录,则必须特别小心,因为这些文件夹可能因 Windows 的每个版本而异,并且还取决于登录的用户in. .NET 框架可以帮助您,只需使用 Environment 类及其成员来处理特殊文件夹:

openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

在本例中,我获得了 My Documents 文件夹的路径,但请查看 SpecialFolder 枚举 - 它包含许多有趣路径的值。

多个文件

如果您的应用程序支持多个打开的文件,或者您只是想使用 OpenFileDialog 一次选择多个文件,则需要启用Multiselect属性。在下一个示例中,我们已经这样做了,作为对您的礼貌,亲爱的读者,我们还应用了上述所有技术,包括过滤和设置初始目录:

<Window x:Class="WpfTutorialSamples.Dialogs.OpenFileDialogMultipleFilesSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="OpenFileDialogMultipleFilesSample" Height="300" Width="300">
    <DockPanel Margin="10">
        <WrapPanel HorizontalAlignment="Center" DockPanel.Dock="Top" Margin="0,0,0,10">
            <Button Name="btnOpenFile" Click="btnOpenFiles_Click">Open files</Button>
        </WrapPanel>
        <ListBox Name="lbFiles" />
    </DockPanel>
</Window>


using System;
using System.IO;
using System.Windows;
using Microsoft.Win32;

namespace WpfTutorialSamples.Dialogs
{
	public partial class OpenFileDialogMultipleFilesSample : Window
	{
		public OpenFileDialogMultipleFilesSample()
		{
			InitializeComponent();
		}

		private void btnOpenFiles_Click(object sender, RoutedEventArgs e)
		{
			OpenFileDialog openFileDialog = new OpenFileDialog();
			openFileDialog.Multiselect = true;
			openFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
			openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
			if(openFileDialog.ShowDialog() == true)
			{
				foreach(string filename in openFileDialog.FileNames)
					lbFiles.Items.Add(Path.GetFileName(filename));
			}
		}
	}
}

如果您测试此代码,您将看到现在可以通过按住CtrlShift并用鼠标单击来选择同一目录中的多个文件。一旦被接受,本示例只需通过循环FileNames属性将文件名添加到 ListBox 控件 。


SaveFileDialog 将帮助您选择位置和文件名。它的工作原理和外观与我们在上一篇文章中使用的 OpenFileDialog 非常相似,但有一些细微的差别。就像 OpenFileDialog 一样,SaveFileDialog 是一个通用 Windows 对话框的包装器,这意味着您的用户无论是在您的应用程序中还是在记事本中启动它,都会看到大致相同的对话框。

首先,让我们从使用 SaveFileDialog 的一个非常简单的示例开始:

<Window x:Class="WpfTutorialSamples.Dialogs.SaveFileDialogSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SaveFileDialogSample" Height="300" Width="300">
    <DockPanel Margin="10">
        <WrapPanel HorizontalAlignment="Center" DockPanel.Dock="Top" Margin="0,0,0,10">
            <Button Name="btnSaveFile" Click="btnSaveFile_Click">Save file</Button>
        </WrapPanel>
        <TextBox Name="txtEditor" TextWrapping="Wrap" AcceptsReturn="True" ScrollViewer.VerticalScrollBarVisibility="Auto" />
    </DockPanel>
</Window>


using System;
using System.IO;
using System.Windows;
using Microsoft.Win32;

namespace WpfTutorialSamples.Dialogs
{
	public partial class SaveFileDialogSample : Window
	{
		public SaveFileDialogSample()
		{
			InitializeComponent();
		}

		private void btnSaveFile_Click(object sender, RoutedEventArgs e)
		{
			SaveFileDialog saveFileDialog = new SaveFileDialog();
			if(saveFileDialog.ShowDialog() == true)
				File.WriteAllText(saveFileDialog.FileName, txtEditor.Text);
		}
	}
}

如您所见,主要是实例化SaveFileDialog然后调用ShowDialog()方法。如果返回 true,我们将使用FileName属性(它将包含所选路径以及用户输入的文件名)作为写入内容的路径。

如果您单击保存按钮,您应该会看到一个这样的对话框,具体取决于您使用的 Windows 版本:

筛选

从第一个示例中可以看出,我手动将 .txt 扩展名添加到我想要的文件名,主要是因为“另存为类型”组合框是空的。就像 OpenFileDialog 一样,这个框是通过Filter属性控制的,它也以完全相同的方式使用。

saveFileDialog.Filter = "Text file (*.txt)|*.txt|C# file (*.cs)|*.cs";

关于 Filter 属性的格式的更多详细信息,请参阅上一篇关于 OpenFileDialog 的文章,那里有详细的解释。

使用上述过滤器,生成的 SaveFileDialog 将如下所示:

有了它,您就可以在不指定扩展名的情况下编写文件名 - 它将取自过滤器组合框中选定的文件类型。这也向用户表明您的应用程序支持哪些文件格式,这当然很重要。

设置初始目录

SaveFileDialog 使用的初始目录由 Windows 决定,但通过使用InitialDirectory属性,您可以覆盖它。您通常会将此值设置为用户指定的目录、应用程序目录或仅设置为上次使用的目录。您可以将其设置为字符串格式的路径,如下所示:

saveFileDialog.InitialDirectory = @"c:\temp\";

如果您想使用 Windows 上的特殊文件夹之一,例如桌面、我的文档或 Program Files 目录,您必须特别小心,因为这些文件夹可能因 Windows 的每个版本而异,还取决于登录的用户.NET 框架可以帮助您,只需使用 Environment 类及其成员来处理特殊文件夹:

saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

在本例中,我获得了 My Documents 文件夹的路径,但请查看 SpecialFolder 枚举

选项

除了本文中已经提到的选项之外,我想提请您注意以下属性,它们将帮助您根据需要定制 SaveFileDialog:

AddExtension - 默认为 true 并确定 SaveFileDialog 是否应自动将扩展名附加到文件名,如果用户省略它。扩展将基于选定的过滤器,除非这是不可能的,在这种情况下,它将回退到DefaultExt属性(如果指定)。如果您希望您的应用程序能够保存没有文件扩展名的文件,您可能必须禁用此选项。

OverwritePrompt - 默认为 true 并确定 SaveFileDialog 是否应在用户输入文件名时要求确认,这将导致现有文件被覆盖。除非在非常特殊的情况下,您通常希望启用此选项。

标题 - 如果您想在对话框上自定义标题,您可以覆盖此属性。它默认为“另存为”或本地化的等效项,并且该属性也对 OpenFileDialog 有效。

ValidateNames - 默认为 true,除非它被禁用,否则它将确保用户在允许用户继续之前只输入有效的 Windows 文件名。

编辑于 2022-05-04 11:38