在Windows 8開發中另外一個非常好的工具:文件選擇器。可以從用戶機器上獲取一個或者多個文件。最后我也會介紹一下如何在用戶機器上選擇一個文件夾。
1. 更新package.appxmanifest,我們與用戶系統進行交互的所有機制,首先都需要更新package.appxmanifest文件。在本文,我們要進行文件的打開和保存,所以所以需要添加相應的聲明。
1)針對文件打開選擇器,需要添加如下內容:

如上圖,有兩個選擇:
支持任何文件類型:選擇這個的話,你的程序就被聲明為可以訪問任意類型的文件。
支持文件類型:在這里指定你想要打開的文件類型,例如你只想讓程序打開Excel文件,那么可以在這里輸入“.xls”。
2)文件保存選擇器的設置也是類似的。如下圖:

2. 從用戶機器上獲取一個文件
1)選擇一個或者多個文件(FileOpenPicker)
本文創建從用戶機器上選擇文件,首先是選擇一個文件,然后是多個文件,接着是選擇指定某種文件類型(如.png)的多個文件。從用戶機器上選擇一個文件,需要從FileOpenPicker對象開始。這個對象會給用戶打開一個文件打開選擇器對話框,幫助用戶選擇一個或者多個文件,然后返回給我們。它有許多選項,我這里會進行介紹。下面是選擇指定文件類型的一個文件的相關代碼:
private async void Button_Click(object sender, RoutedEventArgs e)
{
FileOpenPicker picker = newFileOpenPicker();
picker.ViewMode =PickerViewMode.Thumbnail; //設置文件的現實方式,這里選擇的是圖標
picker.SuggestedStartLocation =PickerLocationId.PicturesLibrary; //設置打開時的默認路徑,這里選擇的是圖片庫
picker.FileTypeFilter.Add(".jpg"); //添加可選擇的文件類型,這個必須要設置
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
IReadOnlyList<StorageFile> files =await picker.PickMultipleFilesAsync(); //選擇打開多個文件
// StorageFile file = await picker.PickSingleFileAsync(); //只能選擇一個文件
if (files != null && files.Count > 0)
{
foreach(var file in files)
{
..........
//對選擇的文件進行相關處理
}
}
}
創建FileOpenPicker時,我們必須設置FileTypeFilter。不允許 提供一個通配符或者忽略該過濾器。你必須提供至少一個文件類型,也可以提供 多個(比如在選擇圖片是,可能會有PNG、JPG、JPEG、GIF和BMP等),當用戶選擇了一個文件后,它將給我們的程 序返回一個StorageFile。 在打開文件打開選擇器的時候,預先指 定一個路徑,比如圖片集合、或音樂,我們可以指定如下用戶電腦中8個位置里 的一個。最后,我們還可以設置文件打開選擇器中如何顯示文件。使用FileOpenPicker 對象的ViewMode屬性即可,如下: picker.ViewMode = PickerViewMode.List; 可選項只有List或Thumbnail,它們顯示出來的樣子不太一樣。Thumbnail只 顯示一個方形圖片,代表一個文件。
2).保存選中的文件到另一個地方(FileSavePicker)
接下來,我們看看如何使用文件選擇器,將文件保存到用戶機器中。 與上面操作相關的一個功能,可能就是我們希望能夠將一個文件保存到用戶機器中。這與將文件保存在程序內部是不同的。在這里,我們是將文件永久的保存在用戶機器中,即使我們的程序被卸載了,保存的文件還存在。如果別的程序不能使用你的文件,這可能不是你想要的一種存儲方法。我建議這種方式存儲的文件一般可以被許多其它程序打開。要實現這樣的文件保存功能,與FileOpenPicker非常類似,只不過使用的是FileSavePicker。 另外一個不同點就是我們將數據寫到用戶的硬盤中。這也就會帶來一些其它問題,比如文件已經被打開,並被其它程序編輯,甚至刪除該文件。所以,我們首先需要啟動文件保存選擇器,讓用戶決定將文件保存在什么地方(同時還有文件類型和文件名),代碼如下:
private async void Save_Click(object sender, RoutedEventArgs e)
{
FileSavePicker picker = newFileSavePicker();
picker.SuggestedStartLocation =PickerLocationId.Desktop;
picker.FileTypeChoices.Add("Image", newList<string>() { ".jpg",".jpeg",".png",".bmp",".gif"});
picker.FileTypeChoices.Add("Text", newList<string>() { ".txt"});
picker.SuggestedFileName =DateTime.Now.ToString("yyyyMMddhhmmss");
StorageFile file =await picker.PickSaveFileAsync();
if (file != null)
{
CachedFileManager.DeferUpdates(file);
IBuffer buffer = awaitFileIO.ReadBufferAsync(storageFile); //storageFile是已經選中要保存的文件
await FileIO.WriteBufferAsync(file,buffer);
FileUpdateStatus status = awaitCachedFileManager.CompleteUpdatesAsync(file);
}
}
在上面代碼中,開始的地方看起來就有點與之前的不同了。不再使用過濾器,而是添加相應的FileTypeChoices,代表用戶可以存儲的不同文件格式。我選擇的
這些choice有點不太相關,不過這可以幫助演示在列表中顯示指定的任意文件類型。這些都是由你來控制的。另外,當用戶選擇了一個位置和對應文件的name后,還沒有完。實際上,選擇器會將這些值返回給我們,下一步就是利用這些值將數據寫入到對應的文件中。在我的if語句中,我使用DeferUpdates()方法來保護正在使用的這個文件不別的程序操作,直到我的操作完成。最后,使用CompleteUpdateAsync()方法來提交這些保存的數據,這就意味着所有的工作都完成。
3).選中一個文件夾(FolderPicker)
從用戶機器上選擇一個文件夾,而不是一個指定的文件。讓用戶來選擇一個默認的存儲位置,或者選擇一個你查找文件的位置。這種處理的一個好處就是當用戶選擇一個文件夾后,我們可以將該文件夾保存為我們的默認文件夾,並且獲得確定的授權:在不需要進行請求訪問下,對該文件夾進行讀寫。下面是相關代碼:
private async void Delete_Click(object sender, RoutedEventArgs e)
{
FolderPicker folder = newFolderPicker();
folder.ViewMode =PickerViewMode.Thumbnail;
folder.SuggestedStartLocation =PickerLocationId.DocumentsLibrary;
folder.FileTypeFilter.Add(".jpeg");
StorageFolder storageFolder = await folder.PickSingleFolderAsync();
if (folder != null)
{
//對文件夾內的文件進行相關處理
.......
StorageApplicationPermissions.FutureAccessList.AddOrReplace("DefaultFolder", storageFolder);
}
}
