This article is currently in the process of being translated into Japanese (~98% done).
The OpenFileDialog
ウィンドウズアプリケーションでファイルをオープンまたはセーブする時はいつでもだいたい同じようなダイアログを使います。これはもちろん、これらのダイアログは Windows API の一部で、ウィンドウズプラットフォームの開発者が利用できるからです。
WPFでは、ファイルオープンとセーブ両方に使える標準のダイアログが Microsoft.Win32 名前空間にあります。この記事では、ファイルオープンとファイルセーブのダイアログが簡単に表示できる OpenFileDialog クラスに焦点を当てます。
単純な OpenFileDialog サンプル
追加オプションなしの OpenFileDialog を使ってテキストボックスにファイルをロードするところから始めましょう。
<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);
}
}
}
Open file ボタンをクリックすると、OpenFileDialog がインスタンス化されて表示されます。使っているWindowsのバージョンとテーマに依存しますが、この様に表示されます。
ShowDialog() は null 可能なブーリアンを返します。これは、false か true か null をとるということです。もしユーザーがファイルを選んで "Open" を押したら結果は True になり、その場合はテキストボックスコントロールにファイルをロードします。ユーザーが選んだファイルの完全パスは、 OpenFileDialogの FileName プロパティを使って得ることが出来ます。
フィルター
アプリケーションでユーザーにファイルをオープンさせたい時、普通は拡張子を1個か2個に制限します。例えばワードは主にWordファイル(拡張子は .doc か .docx)で、ノートパッドなら主にテキストファイル(拡張子は .txt)です。
アプリケーションで、どのタイプのファイルを開くべきかをユーザーに示すために、また、見やすさのためのファイル表示制限として、OpenFileDialog にフィルターを指定できます。これは、上記のサンプルに追加できる以下の Filter プロパティで実行できます。ダイアログを初期化した直後に以下を追加します。
openFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
これが結果です。
今度は、ダイアログにファイルタイプを選択するためのコンボボックスがあり、表示されるファイルが選択されたファイルタイプで指定した拡張子に制限されています。
フィルターとして指定するフォーマットは、最初は少し奇妙に見えるかもしれません。しかし、これは要求する拡張子を人が読めるようにしたものです。そしてこれは、パイプ文字(|)で区切られていて、コンピュータにも解析しやすいものです。ひとつ以上のファイルタイプが必要な場合は、上記の例のように、各組の情報をパイプ文字で区切ってください。
まとめると、後半部分は、"Text files (*.txt)" という名前のファイルタイプを意味していて(括弧の中の拡張子はユーザーにわかりやすくするため、どの拡張子が含まれるのかわかるようにしています)、2番目の部分は、ダイアログに .txt 拡張子のファイルを表示するように指示しています。
Text files (*.txt)|*.txt
もちろんそれぞれのファイルタイプには複数の拡張子を含めることが出来ます。例えば、画像ファイルにはこの様に JPEG と PNG の両方のファイルを指定できます。
openFileDialog.Filter = "Image files (*.png;*.jpeg)|*.png;*.jpeg|All files (*.*)|*.*";
2番目の部分(コンピュータが読む部分)では各拡張子の間をセミコロンで分けています。一方、最初の部分は、好きなフォーマットで書くことが出来ますが、多くの開発者は、上記のサンプルと同じ様に両方の部分で同じ書き方をしているようです。
初期ディレクトリの設定
OpenFileDialog で使われる初期ディレクトリはWindowsによって決められますが、InitialDirectory プロパティを使えば変更できます。普通はこの値をユーザーの指定したディレクトリやアプリケーションのディレクトリ、またはユーザーが最後に使ったディレクトリに設定します。この値は次のようにパスを文字列で指定します。
openFileDialog.InitialDirectory = @"c:\temp\";
Windowsフォルダや My Documents フォルタ、Program Files ディレクトリ等の特別なフォルダを使う場合は特別な注意をしなければなりません。何故ならそれらはウィンドウズのバージョンや、どのユーザーがログインしているかによって変わるかもしれないからです。しかし .NET フレームワークの Environment クラスを使えば、そのメンバが特別なフォルダについて対応してくれます。
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
この場合、My Documents フォルダのパスを取得しています。しかし、特別フォルダの一覧表を見てみると、興味深いパスがたくさん含まれています。全てのパスを知るには、ここを参照して下さい。 MSDN article
複数ファイルの対応
アプリケーションが複数ファイルに対応している場合や、ただ単に OpenFileDialog で1つ以上のファイルを選択する場合は 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));
}
}
}
}
このコードで、Ctrl または Shift を押しながらファイルをクリックすると、同じディレクトリの複数ファイルが選択できることがわかるでしょう。このサンプルでは、OKボタンが押されたら、ループを回して FileNames プロパティから選択されたファイルをリストボックスに追加しています。
まとめ
WPF の OpenFileDialog は簡単に使えて、本当に多くのことを処理してくれます。それと、これらのサンプルでは例外処理がなく、多くのコードが省略されていることに注意してください。ファイルの IO タスクを処理する時は一般的に、ファイルのロックや存在しないファイルパスやこれらに関連する問題が起こりやすいため、常に例外に気をつけておくべきです。